# terrazasfull.cl — Apache 2.4, extract directly into public_html
Options -Indexes -MultiViews
DirectoryIndex index.html
DirectorySlash Off
ErrorDocument 404 /404.html
AddDefaultCharset UTF-8

<IfModule mod_rewrite.c>
RewriteEngine On
# Deny hidden paths, backups, source files and executable uploads; keep ACME available.
RewriteRule (^|/)\.(?!well-known(?:/|$)) - [F,L]
RewriteRule \.(?:env|ini|log|sql|bak|old|orig|swp|map|ts|tsx|jsx|php[0-9]*|phtml|phar|cgi|pl|py|sh)$ - [F,L,NC]
# Canonical domain and HTTPS. Requires an active SSL certificate.
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^terrazasfull\.cl$ [NC]
RewriteRule ^ https://terrazasfull.cl%{REQUEST_URI} [R=301,L,NE]
# Redirect explicit index.html and trailing slashes to clean canonical URLs.
RewriteCond %{THE_REQUEST} \s/+(.*/)?index\.html(?:[?\s]) [NC]
RewriteRule ^(.*/)?index\.html$ /$1 [R=301,L,NE]
RewriteCond %{THE_REQUEST} \s/+[^?\ ]+/(?:[?\s])
RewriteRule ^(.+)/$ /$1 [R=301,L,NE]
# Existing files are served unchanged. Never use an SPA fallback for missing pages.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f
RewriteRule ^(.+?)/?$ $1/index.html [END]
</IfModule>

<FilesMatch "^(?:package(?:-lock)?\.json|bun\.lock|AGENTS\.md|roadmap\.md)$">
Require all denied
</FilesMatch>

<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"
Header always set Strict-Transport-Security "max-age=31536000" "expr=%{HTTPS} == 'on'"
# Each HTML document also has a stricter hash-based script policy in its head.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'none'; frame-ancestors 'none'; upgrade-insecure-requests"
<FilesMatch "\.(?:js|css|jpg|jpeg|png|webp|avif|svg|ico|woff2?)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
<FilesMatch "\.(?:html|xml|txt)$">
Header set Cache-Control "public, max-age=0, must-revalidate"
</FilesMatch>
</IfModule>

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json application/xml text/xml image/svg+xml
</IfModule>
