/* ============================================================================
   footer.css - the folder footer.
   ----------------------------------------------------------------------------
   BRAND OS v3.0 "ATLAS". Every colour below is a token from tokens.css or a
   colour-mix() of one. There is no pasted hex in this file.

   Nothing here is computed at runtime. The ground, the ink, and the five
   folder colours are authored in this sheet and stay where they are put, so
   the footer renders identically with JavaScript blocked. footer.js adds the
   folder open and close and nothing else.

   ---- WHAT CHANGED, AND WHY ------------------------------------------------

   1. THE MARK IS THE REAL LOCKUP. The hand-built 2x2 "DJVF" letter grid is
      gone. v3 1.1 F: the wordmark is artwork, not live text, and it is never
      set in the display face. footer.mjs renders the stacked tagline lockup,
      dark master, at 580x389; .ft3-logo re-sizes it fluidly and never lets it
      fall under the 200px minimum that 3.8 sets for that file.

   2. THE FIVE FOLDER COLOURS ARE THE PALETTE, NOT A LADDER OF IT. This
      reverses what this file said until 2026-08-25, so the reversal is on the
      record. v3 held Landfall and Meridian to be signal only, never
      furniture, and five permanent navigation objects are furniture by
      definition, so the pair was excluded and the folders were a tonal
      ladder of the other three. DJ's ruling replaces that ladder with the
      palette itself. Under the role-bound reading the two colours are not
      decoration here: Company OS is the shipped thing, which is what Landfall
      means, and Demos are informational, which is what Meridian means. The
      per-slot block further down carries the full mapping.

   3. THE DAY CYCLE IS GONE. The four variables at the top of .ft3 were
      rewritten every minute by footer.js from the viewer's clock, and
      footer-sky.js drew a sun, a moon at tonight's phase, and a star field
      over the result. All of it is deleted. The ground is one authored
      gradient: the --grad-ground geometry with its top-left stop moved from a
      light green to True North pulled toward Midnight.

      That deletion took a guarantee with it, so the guarantee is re-made a
      different way. A moving ground could collide with a fixed folder colour,
      and footer.js solved that by measuring every folder each tick and
      nudging its lightness in OKLab. A static ground cannot drift, but two of
      DJ's five colours still collide by construction: Midnight Green on a
      ground whose midpoint is Midnight Green, and Paper White behind papers
      that are near-white. Both are answered by --ft-folder-edge and
      --ft-paper-edge, applied to all five. A rule instead of a computation.

   4. MOTION IS INSIDE THE BUDGET. Everything here is 260ms or a timing token,
      and reduced motion REMOVES the movement rather than shortening it. The
      260ms ceiling governs state changes, the things a person triggers and
      then waits on. Continuous ambient surfaces are exempt under the owner's
      2026-08-26 ruling (see tokens.css) and nothing in this footer is one.

   5. UNDER 560px THE FOLDERS ARE NOT FOLDERS. They render as labelled lists
      of the anchors already in the document. See the media query at the foot
      of this file, and syncList() in footer.js, which owns the keyboard half.
   ========================================================================= */

.ft3 {
  /* 2026-08-25, DJ's call. These four were rewritten every minute by
     footer.js from the viewer's clock. That system is gone, so they are
     authored once, here, and nothing repaints them. */
  --ft-ink:    var(--paper);
  --ft-accent: var(--spark);
  /* 66% ink on ground - the v3 --dim-d formula. #A8B6B7 on Midnight is 7.6:1,
     measured 7.01:1 in the live footer on 2026-08-25. */
  --ft-dim:    color-mix(in oklab, var(--ft-ink) 66%, var(--ink));
  --ft-line:   color-mix(in oklab, var(--ft-ink) 16%, var(--ink));

  /* THE HAIRLINES, and they are load-bearing rather than decorative.
     Folder one is Midnight Green on a ground whose midpoint is Midnight
     Green, so without an edge it is not a dark folder, it is a hole. Folder
     two is Paper White and its three papers are near-white, so without an
     edge the open fan is invisible against its own front. The old fix was
     footer.js measuring each folder against a moving ground and nudging its
     lightness in OKLab; a static ground does not need the computation, it
     needs a rule. Applied to all five so it reads as a system and not as a
     patch on the two that break. */
  --ft-folder-edge: color-mix(in srgb, var(--paper) 18%, transparent);
  --ft-paper-edge:  color-mix(in srgb, var(--chrome) 26%, transparent);

  --ft-paper-1: color-mix(in srgb, var(--chrome) 14%, var(--paper));
  --ft-paper-2: var(--band);
  --ft-paper-3: var(--paper);

  /* THE MARK COLUMN WIDTH, declared once. DJ asked for the CTA to match the
     lockup above it, and two separate clamps that happen to agree today are
     two clamps that disagree the first time either is tuned. Both the logo
     and the button read this. */
  --ft-mark-w: clamp(200px, 18vw, 250px);

  --ft-fade: 260ms;
  --ft-ease: var(--ease);

  /* THE GROUND. Same geometry as --grad-ground, which is what the Operating
     Loop band on the homepage uses and what DJ pointed at. One stop moved:
     the 0% corner was #0A4C4A, a lighter green, and is now True North pulled
     66% toward Midnight. Full-strength spark was tried and read louder than
     the original stop's muted weight, which is the relationship being copied
     rather than the literal colour. 158deg keeps the warm corner top-left and
     lands the dark end bottom-right. */
  position: relative;
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--spark) 66%, var(--ink)) 0%,
    var(--ground) 46%,
    color-mix(in srgb, var(--ink) 68%, black) 100%);
  color: var(--ft-ink);
}

/* The grain, lifted from .band-spark so the two warm grounds on this site are
   made the same way. Purely optical: it stops a large gradient banding. */
.ft3::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.ft3-in { position: relative; max-width: var(--wrap); margin-inline: auto; padding: 72px var(--gutter) 30px; }

/* The mark and the folder row share one line until there is genuinely no room.

   This wrapped on the live site at 1400px, dropping the folders under the mark
   and leaving half the footer empty. The cause was arithmetic, not a rule: both
   children sized themselves from content, and once the logo's clamp() reached
   its 340px ceiling the two intrinsic widths crossed the 1180px wrap and the row
   broke. A layout that holds only while two content widths happen to sum under a
   third is not holding, it is coinciding.

   So the folder row is now the flexible child — it may shrink, it aligns to the
   right edge, and `min-width: 0` lets it actually do so instead of refusing at
   its content width, which is the default and the usual reason a flex child will
   not shrink. */
/* BOTTOMS, NOT TOPS. The folder row carries 74px of padding-top as headroom
   for a fan that opens upward, so top-aligning the two children put the mark
   level with empty space and the folder captions well below the tagline. The
   headroom is structural and cannot be removed, so the alignment moves
   instead: the mark column's last element now sits on the same line as the
   folder captions. */
.ft3-top { display: flex; flex-wrap: wrap; gap: 48px; align-items: flex-end; justify-content: space-between; }
.ft3-markcol { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
.ft3-folders { flex: 1 1 520px; min-width: 0; justify-content: flex-end; }

/* ---- the lockup ----------------------------------------------------------
   Clear space is 0.5 x icon height on all four sides, measured from the bezel
   (§3.7). At the sizes below the icon is 54-77px tall, so the floor is ~27-39px
   of clear band; the 48px flex gap and the 72px top padding both clear it, and
   the margin here holds the bottom edge open when the name lines are dropped.

   The width clamp never resolves below 200px, which is the published minimum
   for the stacked lockup carrying the tagline. Below that §3.8 says the
   tagline is dropped, not shrunk — which is a different FILE, not a smaller
   one, so this sheet refuses to draw it small rather than breaking the rule
   quietly. */
.ft3-mark { flex: 0 0 auto; display: block; max-width: 100%; }

.ft3-logo {
  display: block;
  /* The stacked master is 580x389, so width buys height at 1.49:1 — the
     ceiling stays modest or the mark towers over the folder row. The 200px
     floor is the Brand OS minimum for the stacked tagline lockup (§3.8), so
     the ceiling moves, never the floor. */
  width: var(--ft-mark-w);
  max-width: 100%;
  height: auto;
  margin-bottom: 0;
}

/* ---- the offer -----------------------------------------------------------
   Spark on this ground is a shape-and-large-text use, not small body copy.
   The hollow-to-filled swap is the house state-swap: the same gesture the
   header CTA makes, run in reverse. */
.ft3-cta {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-display); font-size: 14px; font-weight: 700;
  color: var(--spark); text-decoration: none;
  border: 1px solid color-mix(in srgb, var(--spark) 45%, transparent);
  border-radius: 999px; padding: 12px 18px;
  /* matched to the lockup above, per DJ 2026-08-25. box-sizing is border-box
     sitewide, so the padding lives inside the width and the two edges line
     up exactly rather than approximately. */
  width: var(--ft-mark-w);
  justify-content: center;
  transition: background-color var(--ft-fade) var(--ft-ease), color var(--ft-fade) var(--ft-ease),
              border-color var(--ft-fade) var(--ft-ease), box-shadow var(--ft-fade) var(--ft-ease);
}
.ft3-cta svg { flex: 0 0 auto; color: currentColor; }
.ft3-cta:hover {
  background: var(--spark); color: var(--ink); border-color: var(--spark);
  box-shadow: 0 0 0 1px var(--spark), 0 0 16px color-mix(in srgb, var(--spark) 55%, transparent);
}
.ft3-cta:focus-visible { outline: 2px solid var(--ft-accent); outline-offset: 4px; }

.ft3-mark:focus-visible {
  outline: 2px solid var(--ft-accent);
  outline-offset: 10px;
  border-radius: var(--r-sm);
}

/* ---- the folder row ------------------------------------------------------ */
.ft3-folders {
  display: flex;
  flex-wrap: wrap;
  gap: 44px 38px;
  /* headroom so an opened fan never clips into the row above */
  padding-top: 74px;
}
.ft3-cell { display: flex; flex-direction: column; align-items: center; gap: 15px; position: relative; }
.ft3-cap {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .14em;
  transition: color var(--ft-fade) var(--ft-ease);
}

.ft3-folder {
  position: relative;
  cursor: pointer;
  transition: transform var(--ft-fade) var(--ft-ease);
  outline: none;

  /* authored default; the per-slot rules below win on specificity */
  --ft-folder: var(--chrome);
  /* The back panel, one step down from the face. footer.js used to write
     this inline from a darken() call; with the ground static it is just a
     mix, and the authored value is the only value. */
  --ft-folder-back: color-mix(in oklab, var(--ft-folder) 88%, var(--ink));
}

/* THE FIVE, DJ's ruling 2026-08-25, in nav order. These are the palette
   itself rather than a tonal ladder derived from three of it.

     slot     folder       value      token
     chrome   About        #00272C    Midnight Green   var(--ink)
     spark    Work         #FFFFFF    Paper White      var(--paper)
     signal   Company OS   #09E85E    Landfall         var(--signal)
     beacon   Demos        #279AF1    Meridian         var(--beacon)
     deep     Elsewhere    #245D63    Surface Steel    var(--chrome)

   THIS REVERSES WHAT THIS FILE USED TO SAY, so the reversal is written down.
   v3 held that Landfall and Meridian are signal only and never furniture, and
   five permanent navigation objects are furniture, so the pair was excluded
   and the five folders were a tonal ladder of the other three. Under the
   2026-08-25 role-bound palette those two colours mean arrival and motion,
   and the assignment above is not decoration: Company OS is the shipped
   thing, which is what Landfall means, and Demos are informational, which is
   what Meridian means. The Brand OS page has to carry the same reading, or
   the page and the footer disagree about the law in public.

   data-token still names a SLOT rather than a palette token. The slots were
   named when the two were detached and renaming them would touch footer.mjs
   for no gain; the mapping above is the contract. */
.ft3-folder[data-token="chrome"] { --ft-folder: var(--ink); }
.ft3-folder[data-token="spark"]  { --ft-folder: var(--paper); }
.ft3-folder[data-token="signal"] { --ft-folder: var(--signal); }
.ft3-folder[data-token="beacon"] { --ft-folder: var(--beacon); }
.ft3-folder[data-token="deep"]   { --ft-folder: var(--chrome); }

.ft3-folder:focus-visible { outline: 2px solid var(--ft-accent); outline-offset: 12px; border-radius: 4px; }

.ft3-back {
  position: relative;
  width: 112px;
  height: 88px;
  background: var(--ft-folder-back);
  border-radius: 0 8px 8px 8px;
  box-shadow: inset 0 0 0 1px var(--ft-folder-edge);
  transition: background-color var(--ft-fade) var(--ft-ease);
}
.ft3-back::after {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 0;
  width: 40px;
  height: 12px;
  background: var(--ft-folder-back);
  border-radius: 8px 8px 0 0;
  box-shadow: inset 0 0 0 1px var(--ft-folder-edge);
  transition: background-color var(--ft-fade) var(--ft-ease);
}

.ft3-paper {
  position: absolute;
  z-index: 2;
  bottom: 11%;
  left: 50%;
  transform: translate(-50%, 10%);
  width: 72%;
  height: 82%;
  background: var(--ft-paper-1);
  border-radius: 7px;
  /* the resting-sheet shadow, the only one v3 allows at rest */
  box-shadow: var(--sh-sm), inset 0 0 0 1px var(--ft-paper-edge);
  transition: transform var(--ft-fade) var(--ft-ease), box-shadow var(--t-release) var(--ease);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6px;
  /* Midnight on the lightest of the three sheets is 12.73:1; on true
     white it is 15.83:1. There is no second ink. */
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1.15;
  text-decoration: none;
}
.ft3-paper-2 { width: 82%; height: 72%; background: var(--ft-paper-2); }
.ft3-paper-3 { width: 92%; height: 62%; background: var(--ft-paper-3); }

.ft3-front {
  position: absolute;
  z-index: 3;
  inset: 0;
  background: var(--ft-folder);
  border-radius: 8px 12px 12px 12px;
  box-shadow: inset 0 0 0 1px var(--ft-folder-edge);
  transform-origin: bottom;
  transition: transform var(--ft-fade) var(--ft-ease), background-color var(--ft-fade) var(--ft-ease);
}

/* closed hover: the papers peek */
.ft3-folder:not(.is-open):hover { transform: translateY(-5px); }
.ft3-folder:not(.is-open):hover .ft3-paper-1 { transform: translate(-50%, -6%); }
.ft3-folder:not(.is-open):hover .ft3-paper-2 { transform: translate(-50%, -12%); }
.ft3-folder:not(.is-open):hover .ft3-paper-3 { transform: translate(-50%, -18%); }

/* open: the fan is wider than the folder, so it sits above its neighbours */
.ft3-folder.is-open { transform: translateY(-8px); z-index: 40; }
.ft3-folder.is-open .ft3-front { transform: skew(14deg) scaleY(.62); }
.ft3-folder.is-open .ft3-front.is-right { transform: skew(-14deg) scaleY(.62); }

/* Offsets are px, not %, on purpose: the three papers are three different
   sizes, so a % translate moves each a different distance and they pile up. */
.ft3-folder.is-open .ft3-paper-1 { transform: translate(calc(-50% - 74px + var(--mx, 0px)), calc(-32px + var(--my, 0px))) rotate(-15deg); }
.ft3-folder.is-open .ft3-paper-2 { transform: translate(calc(-50% + 74px + var(--mx, 0px)), calc(-32px + var(--my, 0px))) rotate(15deg); }
.ft3-folder.is-open .ft3-paper-3 { transform: translate(calc(-50% + var(--mx, 0px)), calc(-90px + var(--my, 0px))) rotate(2deg); }
/* A fanned sheet is genuinely floating, which is the other shadow token, and
   on hover it takes the house spark-glow: ring, near halo, far halo. Same
   recipe as every other interactive orange on the site, so a sheet you can
   click announces itself the way a button does.

   FOCUS MOVED TO SPARK TOO, and that is a fix rather than a preference. The
   ring used to be var(--ft-folder), the folder's own colour, which was fine
   while the five folders were a tonal ladder of Midnight, Steel and True
   North. DJ's palette put Paper White on the Work folder, and a white focus
   ring on a near-white sheet is not a focus ring. Spark is legible on all
   five and matches the hover, so the two states are one gesture. */
.ft3-folder.is-open .ft3-paper:hover {
  box-shadow: var(--sh-md),
              0 0 0 2px var(--spark),
              0 0 16px color-mix(in srgb, var(--spark) 55%, transparent),
              0 0 34px color-mix(in srgb, var(--spark) 25%, transparent);
}
.ft3-folder.is-open .ft3-paper:focus-visible { outline: 2px solid var(--spark); outline-offset: 3px; }

/* ---- sitemap row and bottom bar ------------------------------------------ */
.ft3-sitemap {
  margin-top: 60px;
  padding-top: 22px;
  border-top: 1px solid var(--ft-line);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  transition: border-color var(--ft-fade) var(--ft-ease);
}
/* Quiet, but not dimmer. Differentiating a label by lowering its contrast is
   how a 10.5px label ends up under the floor: --ft-dim measures 7.01:1 here
   and anything below it starts failing. So this separates itself by being
   mono, uppercase and tracked, at the same contrast as the links it heads. */
.ft3-sitemap-l {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ft-dim);
  padding: 3px 0;
  margin-right: 6px;
  white-space: nowrap;
}

.ft3-sitemap a {
  color: var(--ft-dim);
  text-decoration: none;
  font-size: 12px;
  padding: 3px 0;
  transition: color var(--ft-fade) var(--ft-ease);
}
.ft3-sitemap a:hover { color: var(--ft-ink); text-decoration: underline; text-underline-offset: 3px; }

/* align-items was center, which set the copyright against the vertical
   middle of a note that wraps to two lines and left the row visibly
   untethered. Baseline puts every item on the same first line whatever wraps
   under it. The clock and the moon-phase legend that used to sit on the right
   are gone (2026-08-25), so the row is two items and a spacer. */
.ft3-bottom {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--ft-line);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  align-items: baseline;
  font-size: 12px;
  color: var(--ft-dim);
  transition: border-color var(--ft-fade) var(--ft-ease), color var(--ft-fade) var(--ft-ease);
}
.ft3-bottom a { color: inherit; text-underline-offset: 3px; }
/* The email address is a flex item here, so it is its own box and owes the
   24px target floor; it measured 134x19 on every page (2026-08-27). The
   direct-child selector is deliberate: the "See the gate" link lives inside
   .ft3-note as part of a sentence, and padding that one would break the
   line box for no benefit. */
.ft3-bottom > a { padding-block: 4px; margin-block: -4px; }
.ft3-bottom a:hover { color: var(--ft-ink); }
.ft3-spacer { flex: 1 1 20px; }
.ft3-note { max-width: 62ch; }

@media (max-width: 860px) {
  .ft3-top { gap: 36px; }
  .ft3-folders { gap: 38px 30px; padding-top: 70px; width: 100%; justify-content: flex-start; }
}
/* Under 560px the folders stop being folders.

   THE OLD BEHAVIOUR was a vertical staircase: the same three papers fanning
   upward instead of outward, with 118px of headroom reserved above the grid
   to catch them. It cost a third of a phone screen in blank space, orphaned
   the fifth folder in a two-column grid with an empty cell beside it, and
   still hid all fifteen destinations behind five separate taps.

   THE FIX IS FREE because this footer was built HTML-first: the links are
   real anchors inside .ft3-back at build time, not markup a script creates.
   So the folder graphics are switched off and the anchors already sitting in
   the document reflow as a labelled list. No markup changes, no second
   template, and the fan headroom, the orphan and the taps all go at once.

   footer.js owns the other half: its syncList() strips role, tabindex and
   aria-expanded below this width and returns the papers to the natural tab
   order, because a visible link carrying tabindex="-1" is a link a keyboard
   cannot reach. The 560 here and the LIST_W there are one number in two
   files and must move together. */
@media (max-width: 560px) {
  .ft3 { --ft-mark-w: min(220px, 100%); }
  .ft3-in { padding: 48px var(--gutter) 24px; }
  .ft3-logo { margin-bottom: 0; }
  .ft3-top { flex-direction: column; align-items: stretch; gap: 34px; }
  .ft3-markcol { gap: 18px; }
  .ft3-cta { align-self: flex-start; }

  .ft3-folders {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px 18px;
    padding-top: 0;
    justify-content: stretch;
  }
  .ft3-cell { align-items: stretch; gap: 9px; }
  /* the caption becomes the group heading, so it leads rather than follows */
  .ft3-cap {
    order: -1;
    text-align: left;
    color: var(--spark);
    border-bottom: 1px solid var(--ft-line);
    padding-bottom: 7px;
  }
  .ft3-folder { position: static; cursor: auto; transform: none; }
  .ft3-back {
    width: auto; height: auto;
    background: none; box-shadow: none; border-radius: 0;
    display: flex; flex-direction: column; gap: 2px;
  }
  .ft3-back::after, .ft3-front { display: none; }
  .ft3-paper {
    position: static;
    transform: none;
    width: auto; height: auto;
    background: none; box-shadow: none; border-radius: 0;
    color: var(--ft-ink);
    font-family: var(--font-sans, inherit);
    font-size: 13px;
    font-weight: 500;
    justify-content: flex-start;
    text-align: left;
    /* 40px of touch target, against the 25px the sitemap row scrapes by with */
    padding: 11px 0;
  }
  .ft3-paper:hover { color: var(--ft-accent); }
  /* nothing opens, so nothing may move */
  .ft3-folder:hover, .ft3-folder.is-open { transform: none; }
  .ft3-folder:not(.is-open):hover .ft3-paper,
  .ft3-folder.is-open .ft3-paper { transform: none; }
}

/* v3 law 5: reduced motion REMOVES movement, it never slows it. The folders
   still open and close. Only the travel between the two states goes away. */
@media (prefers-reduced-motion: reduce) {
  .ft3,
  .ft3-cta,
  .ft3-cap,
  .ft3-folder,
  .ft3-back,
  .ft3-back::after,
  .ft3-front,
  .ft3-paper,
  .ft3-sitemap,
  .ft3-sitemap a,
  .ft3-bottom { transition: none; }
  .ft3-folder:not(.is-open):hover { transform: none; }
  .ft3-folder:not(.is-open):hover .ft3-paper-1,
  .ft3-folder:not(.is-open):hover .ft3-paper-2,
  .ft3-folder:not(.is-open):hover .ft3-paper-3 { transform: translate(-50%, 10%); }
}
