/*
 * shared.css
 *
 * Site-wide foundation styles: design tokens, base resets, the .mono
 * utility, top bar, accessibility patterns (Session 2 Level A + Session 2.5
 * Level AA), and scroll-reveal animation base. Plus the prefers-reduced-motion
 * fallback that resets .reveal and .scroll-reveal to their final state.
 *
 * Loaded on every page via <link rel="stylesheet"> in the base layout.
 * Page-specific styles (hero variants, content layouts, page-unique
 * components like the wireframe globe or work timeline) stay inline in
 * the page's template.
 *
 * Extracted from about_v45.html during the SSG migration (forty-fourth
 * arc, 2026-05-16). Source files marked these as "duplicated identically
 * across all five page files until [Session 3 consolidation]." That's
 * what this file is.
 */

:root {
    --ink: #0f0f0e;
    --paper: #f5f7fa;
    --mute: #6a6c70;
    --line: #e5e6ea;
    --line-dark: #2a2a28;
    --accent: #1a1a18;
    --input-border: #7c7e82;
    --wave-ink: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 12'><path d='M0 6 Q 7.5 1 15 6 T 30 6 T 45 6 T 60 6' fill='none' stroke='%230f0f0e' stroke-width='1.5' stroke-linecap='round'/></svg>");
    --wave-paper: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 12'><path d='M0 6 Q 7.5 1 15 6 T 30 6 T 45 6 T 60 6' fill='none' stroke='%23f5f7fa' stroke-width='1.5' stroke-linecap='round'/></svg>");
    /* Mask version of the wave, used by .nav-link::after so the wave color
       follows currentColor (the topbar text color) and stays in sync with
       the topbar's color transition between over-dark and over-light. */
    --wave-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 12'><path d='M0 6 Q 7.5 1 15 6 T 30 6 T 45 6 T 60 6' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/></svg>");
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }

  html { scroll-behavior: smooth; }

  body {
    background: var(--paper);
    color: var(--ink);
    font-family: "Fraunces", Georgia, serif;
    font-optical-sizing: auto;
    font-weight: 380;
    font-variation-settings: "SOFT" 50;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    line-height: 1.5;
    overflow-x: hidden;
  }

  .mono {
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 14px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 400;
  }

/* =========== TOP BAR =========== */
  .topbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 22px 40px;
    color: var(--paper); /* default: hero is in view on load */
    transition: color 0.35s ease;
  }
  .topbar.over-light { color: var(--ink); }
  .topbar.over-dark  { color: var(--paper); }

  .topbar .mono {
    font-size: 16px;
  }
  .topbar a { color: inherit; text-decoration: none; }
  /* Wavy underline on .nav-link uses a ::after pseudo-element instead of
     the linear-gradient cover-shrink pattern that the rest of the site uses
     (Pattern A on .footer-link-text, .contact-value).
     Reason: the topbar's bg behind the wave is dynamic (dark hero or light
     body), and the JS class swap fires at the topbar mid-line (y=36) while
     the wave sits ~14px lower at the bottom of the link. When the dark
     section's edge sits between those two y-positions, the cover layer's
     color (always one of ink/paper) does not match the actual bg behind it
     and shows as a visible solid rectangle.
     The pseudo here drops the cover layer entirely. The wave is a mask
     shape and the visible color is currentColor, so the wave follows the
     topbar's text color through its 0.35s transition. Default state has
     width: 0 so the wave is invisible; on hover, width grows to 100%. */
  .nav-link {
    position: relative;
    display: inline-block;
    padding-bottom: 14px;
    font-size: 16px;
  }
  .nav-link::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 12px;
    width: 0;
    background-color: currentColor;
    -webkit-mask-image: var(--wave-mask);
            mask-image: var(--wave-mask);
    -webkit-mask-size: 60px 12px;
            mask-size: 60px 12px;
    -webkit-mask-repeat: repeat-x;
            mask-repeat: repeat-x;
    -webkit-mask-position: 0 0;
            mask-position: 0 0;
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .nav-link:hover::after { width: 100%; }

/* =========== ACCESSIBILITY (Session 2: Level A) ============
     Patterns added in Session 2 for WCAG 2.1 Level A compliance.
     These will consolidate to the shared stylesheet in Session 3
     (CSS extraction). Duplicated identically across all five page
     files until then.
     ============================================================ */

  /* Visually hidden but accessible to screen readers.
     The standard "sr-only" pattern. Used for the About page H1
     so screen reader users land on a real heading without the
     visible hero changing. Position absolute + 1px size + clip
     rectangle keeps the element in the accessibility tree while
     removing it from layout and from sighted-user view. Do NOT
     swap this for display:none or visibility:hidden — those would
     hide it from screen readers too. */
  .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* Skip link. The first focusable element on the page. Keyboard
     users tab into it, can press Enter to jump past the topbar
     directly to main content. Invisible until focused. Mono utility
     register; paper border so the silhouette reads against any hero
     background (dark or light). z-index 200 sits above the topbar
     (z-index: 100). The button appearing IS the focus indicator —
     no additional outline needed. */
  .skip-link {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    z-index: 200;
  }
  .skip-link:focus {
    top: 20px;
    left: 20px;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    clip-path: none;
    background: var(--ink);
    color: var(--paper);
    border: 1px solid var(--paper);
    padding: 12px 20px;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 14px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 400;
    text-decoration: none;
  }

  /* Current-page indicator on nav links. Adds aria-current="page"
     announcement for screen readers while suppressing the hover
     wavy underline that signals "this is where you can go" — the
     user is already on this page. Link remains clickable (refreshes
     the page) for users who expect that behavior. */
  .nav-link[aria-current="page"] {
    cursor: default;
  }
  .nav-link[aria-current="page"]::after {
    display: none;
  }

/* =========== ACCESSIBILITY (Session 2.5: Level AA polish) ============
     Focus-visible coverage for interactive elements that previously
     relied on browser default focus rings. Matches the existing
     ink-outline-plus-offset pattern used on .work-trigger, .work-panel
     anchors, and gate/modal controls. currentColor adapts to the
     element's text color so the outline reads against both the dark
     topbar/footer and the light topbar on case studies.

     Will consolidate to the shared stylesheet in Session 3 (CSS
     extraction) alongside the Session 2 block above. Duplicated
     identically across all five page files until then.
     ===================================================================== */
  .nav-link:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }
  .footer-works-list a:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }
  .contact-button:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }

  /* =========== TOPBAR WORK MENU (v23) ===========
     The case studies live behind a Work trigger on the right side
     of the topbar, beside About. Hovering or focusing Work reveals
     a small dropdown panel listing the three case studies. Work
     itself does not navigate; it's a hover/focus surface (button
     with aria-haspopup) and carries a small chevron next to its
     label to signal the dropdown.

     The wordmark on the left is a plain home link. The wave
     underline is reserved for the wordmark and the About link;
     Work uses no underline because the chevron carries the
     affordance and the panel is its own visible state.

     Two open paths:
       1. Mouse hover on .work-menu (any part) -> panel reveals.
       2. Keyboard focus inside .work-menu -> panel reveals.
     A small invisible bridge below the trigger lets the cursor
     cross the gap into the panel without losing hover.

     Mobile: the menu stays visible. Tap on the button focuses it,
     focus-within reveals the panel; tap outside removes focus,
     panel hides. The homepage's Selected Work list is the
     no-hover fallback. */
  .left {
    display: flex;
    align-items: center;
  }
  .right {
    display: flex;
    align-items: center;
    gap: 28px;
  }

  .work-menu {
    position: relative;
  }
  .work-trigger {
    /* button reset; type and color come from .topbar .mono parent */
    appearance: none;
    background: transparent;
    border: 0;
    margin: 0;
    /* bottom padding matches .nav-link wave-clearance so Work and
       About align on a shared baseline under flex align-items: center */
    padding: 0 0 14px 0;
    font: inherit;
    font-size: 16px; /* explicit override: font: inherit on <button> can render off vs adjacent <a> in some browsers */
    letter-spacing: inherit; /* same UA-button issue as font-size: form-control defaults can override inherited letter-spacing */
    color: inherit;
    text-transform: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .work-trigger:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 4px;
  }
  /* Hover bridge: invisible strip below the trigger so the cursor
     can move from button to panel without leaving .work-menu. */
  .work-trigger::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: 8px;
  }
  .work-caret {
    width: 10px;
    height: 10px;
    flex-shrink: 0;
    transition: transform 0.20s ease;
  }
  .work-menu:hover .work-caret,
  .work-menu:focus-within .work-caret {
    transform: rotate(180deg);
  }

  .work-panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    display: flex;
    flex-direction: column;
    min-width: 220px;
    /* panel is always paper-on-ink regardless of .topbar over-dark
       or over-light state; the topbar text color shift behind the
       panel doesn't show through */
    background: var(--paper);
    color: var(--ink);
    border: 1px solid var(--line);
    box-shadow: 0 8px 24px rgba(15, 15, 14, 0.08);
    padding: 8px 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition:
      opacity 0.20s ease,
      transform 0.20s ease,
      visibility 0s linear 0.20s;
  }
  .work-menu:hover .work-panel,
  .work-menu:focus-within .work-panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition:
      opacity 0.20s ease,
      transform 0.20s ease,
      visibility 0s linear 0s;
  }
  .work-panel a {
    display: block;
    padding: 8px 16px;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 0.15s ease;
  }
  .work-panel a:hover,
  .work-panel a:focus-visible {
    background: rgba(15, 15, 14, 0.05);
  }
  .work-panel a:focus-visible {
    outline: 1px solid var(--ink);
    outline-offset: -1px;
  }

  /* Reduced-motion fallback handled by the global rule below
     (search "prefers-reduced-motion"); it zeroes all transitions
     so the panel appears and disappears instantly. */

  /* Mobile: keep the menu visible. The button is tap-focusable and
     focus-within reveals the panel; tap outside removes focus and
     hides it. Same hover-only constraint the previous pattern had. */
  @media (max-width: 720px) {
    .right { gap: 18px; }
  }

/* =========== ENTRANCE / SCROLL =========== */
  .reveal {
    opacity: 0;
    transform: translateY(18px);
    animation: fadeUp 1s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }
  @keyframes fadeUp {
    to { opacity: 1; transform: translateY(0); }
  }
  .d1 { animation-delay: 0.15s; }
  .d2 { animation-delay: 0.30s; }
  .d3 { animation-delay: 0.50s; }
  .d4 { animation-delay: 0.70s; }
  .d5 { animation-delay: 0.90s; }
  .d6 { animation-delay: 1.10s; }

  /* Hidden state scoped to .js so non-JS clients see content. */
  .js .scroll-reveal {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 1s cubic-bezier(0.22, 1, 0.36, 1), transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .js .scroll-reveal.in-view {
    opacity: 1;
    transform: translateY(0);
  }

/* =========== REDUCED MOTION ============
   Lifted from the per-page @media (prefers-reduced-motion: reduce) blocks
   shipped in the forty-first arc. Reduced-motion users get the final
   rendered state immediately (no fadeUp, no scroll-reveal animation).
   The v29 .reveal { opacity: 1 } line is here to fix the upstream bug
   where reduced-motion users saw permanently invisible hero content. */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
  .js .scroll-reveal { opacity: 1; transform: none; }
  .reveal { opacity: 1; transform: none; }
}
