/* MAANUKA — site layer. The page-level compositions, expressed as classes. Everything here
   resolves to the semantic token roles; no raw hexes except the one the design itself names
   (the nite link-hover ink, which has no token).

   Load order, and it matters:
     tokens/colors → typography → spacing → ai → semantic → theme
     components.css → ai-components.css        (the design-system component layer, verbatim)
     site.css                                  (this file, last)

   tokens/ai.css must load BEFORE tokens/theme.css. Both declare at the same specificity
   (:root vs [data-theme="nite"]), so ai.css last would beat the nite block and ship day's
   glass and day's verification hues onto the dark ground.

   Scope: the site is two pages — a hero-only landing and the contact page — plus a 404.
   Rules for the retired sections (services, approach, proof, case notes) were stripped on
   2026-08-27; they are recoverable from git history alongside the markup they styled. */

/* — page shell — */
html,body{margin:0}
body{background:var(--surface-page);color:var(--text-body);font-family:var(--font-body)}
.page{min-height:100vh;display:flex;flex-direction:column}
.page>main{flex:1}
a{color:var(--text-link);text-decoration:none}
a:hover{color:var(--accent-fill-active)}
[data-theme="nite"] a:hover{color:#FAD8CC}
.eyebrow{margin:0}
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;padding:10px 16px;background:var(--accent-fill);color:var(--text-on-accent);font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.skip-link:focus{left:0;color:var(--text-on-accent)}

/* — nav —
   The theme toggle sits OUTSIDE .nav-links on purpose: .nav-links is what collapses on
   narrow viewports, and the ground control has to stay reachable when it is closed. On
   desktop the 24px flex gap puts it exactly where the design has it. */
.nav{position:relative;z-index:20}
/* .nav a:not(.btn) is (0,2,1) and would win over a bare .nav-brand, dropping the wordmark to
   quiet ink; match its specificity to keep the brand at full strength. */
.nav a.nav-brand,.nav a.nav-brand:hover{color:var(--color-text)}
.nav-brand-text{display:flex;flex-direction:column}
.nav-brand-text .tagline{font-size:9px}
.nav-links{display:flex;align-items:center;gap:24px}
.nav-toggle{display:none;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:1px solid var(--border-hairline);border-radius:var(--radius-control);background:transparent;color:var(--text-quiet);cursor:pointer}
.nav-toggle:hover{background:var(--surface-hover)}

/* Reserve the scrollbar gutter on every page. Without it a short page (the hero, the 404)
   has no scrollbar and a long one (get-in-touch) does, so moving between them changes the
   viewport width by the scrollbar and everything centred or right-aligned jumps — the nav
   included. Reserving it always costs a few pixels of width and buys a header that does not
   move between pages. */
html{scrollbar-gutter:stable}

/* — footer — */
/* 18px, not 32px: the footer is one line of 10px mono on each side, so the old padding was
   sizing a band for content that does not fill it. */
.site-footer{padding:18px 48px;border-top:1px solid var(--border-hairline);display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap}

/* Reveal on arrival. PROGRESSIVE ENHANCEMENT, and deliberately fail-safe: the hidden state
   lives behind [data-reveal], an attribute only site.js adds, and only when the visitor has
   not asked for reduced motion. No JS, old browser, or reduce-motion → the attribute is never
   set, the rules below never match, and the footer is simply visible. A footer that a script
   has to un-hide is a footer that disappears the moment the script does. */
.site-footer[data-reveal]{opacity:0;transform:translateY(10px);transition:opacity .45s ease,transform .45s ease}
.site-footer[data-reveal][data-revealed]{opacity:1;transform:none}
.site-footer-links{display:flex;align-items:center;gap:20px}
.footer-link,.footer-copy{font-family:var(--font-mono);font-size:10px;letter-spacing:.06em}
.footer-copy{color:var(--text-faint)}
/* Footer links carry the accent as an underline rather than as ink, so the pigment reads on
   both grounds without recolouring 10px mono type. --accent-fill is Kokowai (#A8442A) on day
   and the design system's lifted ochre (#E5866A) on nite — one token, both grounds. Scoped to
   the footer element, not just .footer-link, so any URL added there inherits the treatment.

   Hover REMOVES the underline — the inverse of the design system's own a:hover, which adds
   one. That rule is (0,1,1) and this is (0,2,1), so it wins without !important. The link
   still answers the cursor: the a:hover above shifts the ink. */
.site-footer a{text-decoration:underline;text-decoration-color:var(--accent-fill);text-decoration-thickness:1px;text-underline-offset:3px}
.site-footer a:hover{text-decoration:none}

/* Current page. build.py sets aria-current on exactly one nav item; all the styling hangs
   off it here so the marker itself stays semantic. components.css only lifts the ink of a
   plain link, which says nothing at all when the current page IS the button — so both the
   link case and the button case are answered. */
.nav a:not(.btn)[aria-current="page"]{text-decoration:underline;text-decoration-color:var(--accent-fill);text-decoration-thickness:1px;text-underline-offset:5px}
/* Every nav button is the same variant, so one rule covers the current page on both grounds.
   The ring is --text-on-accent: white over the ochre fill on day, the near-black ground ink
   on nite — the ink that already sits on that fill, so it reads as an inlay rather than a
   colour dropped on top. The earlier two-variant version had Home bordered with dark ink on
   day while the CTA was white-on-ochre, which is exactly the mismatch this removes. */
.nav a.btn[aria-current="page"],.nav a.btn[aria-current="page"]:hover{background:var(--accent-fill-active);box-shadow:inset 0 0 0 1.5px var(--text-on-accent)}

/* Reserve the toggle's box before the script fills it. site.js builds the button, so until
   it runs this span is an empty inline element 0px wide — and the nav then jumped 34px the
   moment the button appeared. Measured: .nav-links.left went 916.2 -> 882.2 on every single
   load. Holding the space here means the button lands in a slot that was always its size. */
[data-theme-toggle-mount]{display:inline-flex;flex:none;width:34px;height:34px}

/* — ground toggle — one round icon button, built by site.js, showing the ground it will
     switch TO. Styled here rather than inline in the script so hover and focus are ONE rule
     driven by tokens. The old segmented control had no hover state at all — only a selected
     accent fill — which is why day and nite responded differently to the cursor. They now
     share the mechanism: --surface-hover is ink-alpha on day and white-alpha at roughly
     double on nite, which is the design system's deliberate answer to the same veil being
     invisible on a near-black ground. It also no longer needs a narrow-viewport rule: one
     34px button fits every width the nav has to hold. */
.ground-toggle{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border:1px solid var(--border-hairline);border-radius:var(--radius-pill);background:transparent;color:var(--text-quiet);cursor:pointer;transition:background var(--dur) var(--ease),color var(--dur) var(--ease),border-color var(--dur) var(--ease)}
.ground-toggle:hover{background:var(--surface-hover);color:var(--color-text);border-color:var(--border-strong)}
.ground-toggle:active{background:var(--surface-pressed)}
.ground-toggle svg{display:block}

/* — shared — */
.actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.btn-nav{font-size:13px}
.mono-label{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-faint)}

/* — photography band — the content wrapper is pinned to nite in both grounds because the
     scrim is dark; data-bare keeps the photo visible behind it. — */
.photo-band{border-radius:0}
.photo-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.photo-content-tight{position:relative;padding:92px 48px}

/* ————————————————— Landing (hero) ————————————————— */
.hero{padding:112px 48px 92px}
.hero-inner{max-width:760px;margin:0 auto;text-align:center;display:flex;flex-direction:column;gap:20px;align-items:center}
.hero-title{font-family:var(--font-heading);font-weight:600;font-size:58px;line-height:1.06;letter-spacing:-.018em;margin:0;text-wrap:balance}
.hero-sub{margin:0;font-size:17px;line-height:1.7;color:var(--text-muted);max-width:560px;text-wrap:pretty}
.hero-actions{display:flex;gap:12px;margin-top:10px;flex-wrap:wrap;justify-content:center}

/* ————————————————— Centred message block (404) ————————————————— */
.cta{padding:96px 48px}
.cta-inner{max-width:720px;margin:0 auto;display:flex;flex-direction:column;gap:18px;align-items:center;text-align:center}
.cta-title{font-family:var(--font-heading);font-weight:600;font-size:34px;line-height:1.15;letter-spacing:-.01em;margin:0}
.cta-sub{margin:0;font-size:16px;line-height:1.7;color:var(--text-muted);max-width:520px;text-wrap:pretty}
.cta-inner .btn{margin-top:6px}

/* ————————————————— Get in touch ————————————————— */
.git-hero-inner{max-width:720px;margin:0 auto;display:flex;flex-direction:column;gap:14px}
.git-title{font-family:var(--font-heading);font-weight:600;font-size:48px;line-height:1.08;letter-spacing:-.016em;margin:0;text-wrap:balance}
.git-hero-sub{margin:0;font-size:16px;line-height:1.7;color:var(--text-quiet);max-width:520px;text-wrap:pretty}
.git-body{padding:80px 48px}
.git-grid{max-width:1000px;margin:0 auto;display:grid;grid-template-columns:minmax(300px,1.35fr) minmax(240px,1fr);gap:64px;align-items:start}
.git-form{display:flex;flex-direction:column;gap:22px}
.field-group{display:flex;flex-direction:column;gap:12px}
.tag-row{display:flex;flex-wrap:wrap;gap:8px}

/* Topic tags. At rest they are exactly the DS accent chip the design shows; selection adds a
   filled state so a multi-select is actually readable as one. Not colour alone — the checkmark
   carries it too, and aria-pressed carries it to assistive tech. */
.tag-toggle{border:0;cursor:pointer;font-size:10px;gap:5px;transition:background var(--dur) var(--ease),color var(--dur) var(--ease)}
.tag-toggle:hover{background:var(--accent-fill-hover);color:var(--text-on-accent)}
.tag-toggle[aria-pressed="true"]{background:var(--accent-fill);color:var(--text-on-accent)}
.tag-toggle .tick{width:0;overflow:hidden;transition:width var(--dur) var(--ease)}
.tag-toggle[aria-pressed="true"] .tick{width:9px}

.form-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.sent-note{font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-ink)}
.form-error{font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--color-critical)}
.field-error{display:block;margin-top:6px;font-family:var(--font-mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--color-critical)}
/* The slot is always in the DOM so screen readers have a stable live region to announce into,
   but an empty block still costs its margin — which made the validated fields taller than the
   optional one before a single error existed. */
.field-error:empty{display:none}
.input[aria-invalid="true"]{border-color:var(--color-critical)}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.git-aside{display:flex;flex-direction:column;gap:28px}
.aside-block{display:flex;flex-direction:column;gap:10px}
.aside-text{margin:0;font-size:15px;line-height:1.65;color:var(--text-muted);text-wrap:pretty}

/* ————————————————— Reflow —————————————————
   The designs are desktop-only. Nothing below redesigns anything: grids stack, the nav
   collapses, and the display type steps down so a 58px headline does not run off a 375px
   screen. Desktop values above are untouched. */
@media (max-width:900px){
  .git-grid{grid-template-columns:1fr;gap:44px}
}
@media (max-width:820px){
  .nav{flex-wrap:wrap;padding:16px 24px}
  .nav-toggle{display:inline-flex}
  .nav-links{display:none;order:3;flex-basis:100%;flex-direction:column;align-items:flex-start;gap:16px;padding:14px 0 4px}
  .nav[data-open="true"] .nav-links{display:flex}
}
@media (max-width:700px){
  .hero{padding:72px 24px 64px}
  .hero-title{font-size:38px}
  .hero-sub{font-size:16px}
  .cta,.git-body{padding-left:24px;padding-right:24px}
  .cta{padding-top:64px;padding-bottom:64px}
  .git-body{padding-top:56px;padding-bottom:56px}
  .photo-content-tight{padding:64px 24px}
  .cta-title{font-size:28px}
  .git-title{font-size:34px}
  .site-footer{padding:14px 24px}
}
@media (max-width:420px){
  .hero-title{font-size:32px}
  .git-title{font-size:29px}
  .hero-actions{flex-direction:column;align-self:stretch}
  .hero-actions .btn{width:100%}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}
