/* fatacquire.com — "Graphite & Slate".
   The identity system is specified in docs/brand/README.md. Read the derived
   values section there before touching .mark: three of its numbers were solved
   analytically, not chosen, and getting them wrong is visible.

   This file shares no colour, no layout primitive and no class name with the
   other public site on this Pages project. Fonts are duplicated under
   /fatacquire/assets so every asset resolves through this site's own
   hostname-scoped path and never depends on a URL owned by the other brand.
   Routing lives in functions/_middleware.js. */

/* The monogram is the one place the 900 weight is load-bearing: a fallback
   grotesk inside the plate reads as a different company's mark, so that face
   blocks briefly rather than swapping. It is preloaded in <head>, so the block
   period is effectively zero. Text faces swap. */
@font-face{font-family:"Libre Franklin";font-style:normal;font-weight:400;font-display:swap;src:url(/assets/fonts/libre-franklin-400.woff2) format("woff2")}
@font-face{font-family:"Libre Franklin";font-style:normal;font-weight:600;font-display:swap;src:url(/assets/fonts/libre-franklin-600.woff2) format("woff2")}
@font-face{font-family:"Libre Franklin";font-style:normal;font-weight:900;font-display:block;src:url(/assets/fonts/libre-franklin-900.woff2) format("woff2")}
@font-face{font-family:"Lora";font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/lora-500.woff2) format("woff2")}

/* ---------------------------------------------------------------------------
   Tokens
   Text opacity is the second tier, not a second grey: 0.82 body, 0.62 status
   label, 0.45 footer meta.
   --------------------------------------------------------------------------- */
:root{
  color-scheme: light dark;

  --ink:#16181A;
  --paper:#F1F2F3;
  --accent:#46586E;
  /* Every rule on the page is the accent, held back to hairline weight. The
     accent used to appear only as a 5px dot and a hover state, which the owner
     read as decoration that never earned its place. Carrying the dividers as
     well gives it one consistent meaning — it is the colour the page draws
     lines in — without adding a second loud element. */
  --hairline:rgba(70, 88, 110, 0.30);
  --hairline-strong:rgba(70, 88, 110, 0.48);

  --plate:var(--ink);
  --glyph:var(--paper);

  --sans:"Libre Franklin", Helvetica, Arial, sans-serif;
  --serif:"Lora", Georgia, serif;

  --edge:clamp(24px, 4.5vw, 56px);
  /* The 9vh term governs from roughly 1240px up, so the desktop rhythm is the
     specified clamp(48px, 9vh, 110px). Below that the vw term takes over and
     keeps the page on one screen on a phone, where 9vh alone overran it. */
  --stack:clamp(28px, min(9vh, 7.5vw), 110px);
}

/* The Reversed colourway from the identity sheet, used as dark mode.
   #46586E is only 2.49:1 on #16181A, so the accent lifts. #8296B0 measures
   5.98:1 against the dark ground, which clears AA for the hover text colour
   and comfortably clears the 3:1 non-text threshold for the status dot. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ink:#F1F2F3;
    --paper:#16181A;
    --accent:#8296B0;
    --hairline:rgba(130, 150, 176, 0.38);
    --hairline-strong:rgba(130, 150, 176, 0.55);
    --plate:#F1F2F3;
    --glyph:#16181A;
  }
}
:root[data-theme="dark"]{
  --ink:#F1F2F3;
  --paper:#16181A;
  --accent:#8296B0;
  --hairline:rgba(130, 150, 176, 0.38);
  --hairline-strong:rgba(130, 150, 176, 0.55);
  --plate:#F1F2F3;
  --glyph:#16181A;
}
:root[data-theme="dark"]{color-scheme:dark}
:root[data-theme="light"]{color-scheme:light}

/* ---------------------------------------------------------------------------
   Page
   --------------------------------------------------------------------------- */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  /* Header, statement and footer share one measure and sit centred. Letting
     the header and footer span the whole window while the copy stopped at its
     own max-width left the footer meta stranded in the far corner on a wide
     screen. The background still fills the viewport: a background set on body
     propagates to the canvas. */
  max-width:900px;
  margin-inline:auto;
  /* svh, not vh: the page is sized to one screen, and svh is the height with
     the mobile browser chrome showing. vh would clip under it; dvh would
     resize the whole layout as the URL bar hides. */
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  gap:var(--stack);
  padding:var(--edge);
  /* The page runs edge to edge, so a notched phone in landscape would put the
     wordmark under the sensor housing without this. */
  padding-left:max(var(--edge), env(safe-area-inset-left));
  padding-right:max(var(--edge), env(safe-area-inset-right));
  padding-bottom:max(var(--edge), env(safe-area-inset-bottom));
  background:var(--paper);
  color:var(--ink);
  font-family:var(--sans);
  font-weight:400;
  -webkit-font-smoothing:antialiased;
}

p{margin:0}
h1{margin:0;font-weight:500}
a{color:inherit;text-decoration:none}
::selection{background:var(--ink);color:var(--paper)}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px}

/* ---------------------------------------------------------------------------
   The mark
   Square plate, letterforms cropped tight. Reproducible from CSS alone, which
   is why it stays sharp at favicon size.

   --mark-size is the plate edge. The glyph is 84% of it: the ink box is
   0.84em wide by 0.752em tall, so its half-diagonal is 0.564em, and a circle
   crop of diameter D needs fontSize <= 0.887 * D. Do not raise 0.84 to make
   the mark look bolder — above ~0.88 the bottom right of the `a` clips in
   every circle-cropped avatar.

   padding-right compensates the trailing letter-space. CSS applies
   letter-spacing after the last character too, so with -0.085em the text box
   is short on the right and centring the box leaves the ink right of true
   centre. The value is per glyph string; see docs/brand/README.md to recompute.

   translateY(0.005em) cancels the 0.005em offset between the ink centre and
   the line box centre at line-height 0.68 with Libre Franklin's metrics. */
.mark{
  width:var(--mark-size);
  height:var(--mark-size);
  flex:none;
  display:grid;
  place-items:center;
  overflow:hidden;
  background:var(--plate);
}
.mark > span{
  display:block;
  font-family:var(--sans);
  font-weight:900;
  font-size:calc(var(--mark-size) * 0.84);
  line-height:0.68;
  letter-spacing:-0.085em;
  white-space:nowrap;
  color:var(--glyph);
  padding-right:0.059em;
  transform:translateY(0.005em);
  user-select:none;
}

/* ---------------------------------------------------------------------------
   Header
   --------------------------------------------------------------------------- */
.masthead{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  /* Below roughly 560px the lockup and the status line together are wider than
     the content box. Wrapping puts the status line on its own row instead of
     overflowing. Above it, this never triggers and the row is as designed.
     32px is specified as the gap BETWEEN the two, so it belongs on the column
     axis only; carried onto the row axis it makes the wrapped header a third
     taller than it needs to be on the one screen where height is scarcest. */
  flex-wrap:wrap;
  column-gap:32px;
  row-gap:14px;
}

.lockup{
  --mark-size:34px;
  display:flex;
  align-items:center;
  gap:12px;
  /* A 34px mark is under the 44px touch target minimum. The padding buys the
     hit area and the negative margin gives back the space, so the visual
     geometry is untouched. */
  padding:5px;
  margin:-5px;
}
/* Named, not `span:last-child`. The glyph inside .mark is also a last-child
   span, and a positional selector here silently restyled the monogram to the
   wordmark's 19px/600 — inside its own plate, where it is meant to be
   28.56px/900. */
.wordmark{
  font-size:19px;
  font-weight:600;
  letter-spacing:-0.025em;
}
.lockup:hover{color:var(--accent)}

.masthead-aside{
  display:flex;
  align-items:center;
  gap:18px;
  margin-left:auto;
  padding-top:9px;
}

.status{
  display:flex;
  align-items:center;
  gap:10px;
}
.status-dot{
  width:5px;
  height:5px;
  flex:none;
  border-radius:50%;
  background:var(--accent);
}
.status span:last-child{
  font-size:11.5px;
  font-weight:600;
  letter-spacing:0.14em;
  text-transform:uppercase;
  opacity:0.62;
}

/* The only interactive control on the page. Inline SVG rather than an image:
   the no-artwork rule in the identity sheet is about the brand mark, not UI. */
.theme-toggle{
  flex:none;
  display:grid;
  place-items:center;
  width:44px;
  height:44px;
  margin:-13px -12px -13px 0;
  padding:0;
  border:0;
  background:none;
  color:inherit;
  opacity:0.5;
  cursor:pointer;
  transition:opacity 0.25s ease, color 0.25s ease;
}
.theme-toggle:hover{opacity:1;color:var(--accent)}
.theme-toggle svg{display:none;width:16px;height:16px}
.theme-toggle svg.is-shown{display:block}
/* Without JavaScript neither icon is marked shown, so the control would be an
   empty box. Hide it entirely instead; the OS preference still drives the
   colourway through the media query above. */
.no-js .theme-toggle{display:none}

/* ---------------------------------------------------------------------------
   Main
   --------------------------------------------------------------------------- */
/* The page is three short texts. The handoff sized it for a 1240px measure
   with the body in two columns, which on a wide screen left a lot of air
   around very little copy and pushed the headline to 88px. Owner, seeing it
   live: too large, too wide, and the second paragraph belongs below the first
   rather than beside it. So the composition is tighter — one column, a
   readable measure, and a headline that is still the loudest thing on the
   page without shouting. */
main{
  flex:1;
  display:grid;
  grid-template-columns:minmax(0, 1fr);
  align-content:center;
  gap:clamp(28px, 3.4vw, 44px);
  width:100%;
}

.statement{
  font-family:var(--serif);
  font-size:clamp(33px, 4.6vw, 54px);
  line-height:1.08;
  letter-spacing:-0.022em;
  text-wrap:balance;
}

/* One column at every width. Two columns of four lines each read as a layout
   problem rather than a composition, and stacking removes the 320px overflow
   the two-column track used to cause. */
.body-copy{
  display:flex;
  flex-direction:column;
  gap:1.15em;
  max-width:60ch;
}
.body-copy p{
  font-size:clamp(15px, 1.02vw, 16.5px);
  line-height:1.6;
  letter-spacing:-0.006em;
  opacity:0.82;
  text-wrap:pretty;
}

/* ---------------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------------- */
/* Baseline, not flex-end. The footer holds two utility rows at the same 0.45
   tier, the CONTACT label and the colophon meta, and sitting them on one
   shared baseline draws a band under the rule that the eye reads as a single
   line. Bottom alignment instead put the meta level with "Email us", so the
   quietest text on the page shared a line with the loudest, and the diagonal
   of empty space between them was the widest gap in the composition.
   Baseline rather than flex-start because the two rows are set at different
   sizes, 11.5px and 12.5px, and aligning their boxes leaves them a pixel
   apart. */
.colophon{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  justify-content:space-between;
  gap:28px;
  padding-top:clamp(24px, 3vw, 40px);
  border-top:1px solid var(--hairline);
}

/* The stack is two groups, not three evenly spaced lines. The label belongs to
   the sentence it introduces, so it sits close to it; the call to action is the
   thing being separated out, so the air goes above it (on .contact-links). A
   flat gap made the three read as one undifferentiated block. */
.contact{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:7px;
}
.label{
  font-size:11.5px;
  font-weight:600;
  letter-spacing:0.14em;
  text-transform:uppercase;
  opacity:0.45;
}
/* Shared treatment for the contact links. Size is deliberately NOT set here.
   The 404 page's .home-link declares its own ramp, and this selector outranks
   it on specificity, so a size here silently overrode the size that page asked
   for. Each link now owns its own ramp. */
.contact a{
  font-family:var(--serif);
  letter-spacing:-0.015em;
  align-self:flex-start;
  max-width:100%;
  overflow-wrap:anywhere;
  border-bottom:1px solid var(--hairline-strong);
  padding-bottom:3px;
  transition:color 0.25s ease, border-color 0.25s ease;
}
.contact a:hover{color:var(--accent);border-bottom-color:var(--accent)}

/* The one commercial line on the page: the footer says the portfolio buys.
   It takes the 0.82 body tier, not the 0.62 label tier it used to share with
   the status line. It is prose that asks the reader for something, and at 0.62
   the only sentence on the page with a commercial job read as fine print.
   The measure holds the sentence on one line wherever there is room for it.
   At 38ch it wrapped to two ragged lines even on a desktop with 788px of
   footer to work with, which read as a paragraph rather than as the single
   offer it is. The sentence sets at 445px, so 52ch clears it with margin for
   a font that loads slightly wide, and still caps the measure if the copy
   grows. It wraps on its own once the screen is too narrow. */
.sell-note{
  font-size:13.5px;
  line-height:1.55;
  opacity:0.82;
  max-width:52ch;
  text-wrap:pretty;
}

.contact-links{
  display:flex;
  align-items:center;
  /* The air that groups the stack: 7px binds label to sentence, 18px total
     (7 + 11) separates the sentence from the call to action. */
  margin-top:11px;
  gap:4px;
}
/* The ramp tops out at 21px, not the 25px the rest of the serif scale used to
   reach here. At 25px the words outweighed the mark beside them badly enough
   that the pair stopped reading as one row, which is what the owner saw. The
   19px floor is unchanged: the imbalance was never a phone problem, because
   the clamp already sat on its floor there and the two were close in size.
   Both links on this row share the ramp, so the mark tracks the words. */
.contact-links a{font-size:clamp(19px, 1.7vw, 21px)}
/* The X glyph is drawn inline so the site stays self-contained (the brand
   isolation suite bans assets outside this directory). It opts out of the
   serif underline treatment the text links carry.

   It is the third control on the site and was the only one under the 44px
   touch minimum, so it buys the hit area the same way .lockup and
   .theme-toggle do: padding out to 44px, negative margin to give the space
   back. translateY centres the glyph on the words rather than on the link box,
   whose 4px of underline padding sits below the text and dragged the icon low.

   The glyph is 0.87em, which is not a taste value. A mark set beside words
   reads as their peer when its height matches their cap height, and a fixed
   pixel size cannot hold that through a clamp. Lora's cap height is 0.7067em
   (measured off a rendered E, not taken from a spec sheet) and this path fills
   19.5 of the 24 viewBox units, so the box has to be 0.7067 / 0.8125 = 0.87em
   for the mark and the capitals to stand the same height at every width.
   Recompute it if either the face or the path changes.

   Opacity 0.6, up from 0.5: at cap height the mark carries more ink, and 0.5
   left it looking washed rather than quiet. */
.contact a.x-link{
  align-self:center;
  border-bottom:none;
  padding-bottom:0;
  display:grid;
  place-items:center;
  width:44px;
  height:44px;
  margin:-11px -12px -11px 0;
  transform:translateY(-2px);
  opacity:0.6;
  transition:opacity 0.25s ease, color 0.25s ease;
}
.contact a.x-link:hover{opacity:1;color:var(--accent)}
.x-link svg{width:0.87em;height:0.87em;display:block}

.colophon-meta{
  display:flex;
  align-items:center;
  gap:22px;
  font-size:12.5px;
  letter-spacing:0.01em;
  opacity:0.45;
}

/* ---------------------------------------------------------------------------
   Entrance
   Three staggered reveals on load, then nothing moves again.
   Guarded rather than merely overridden: these use fill-mode both, so a
   visitor whose animations never run must not be left at opacity 0.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference){
  @keyframes riseIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
  @keyframes fadeIn{from{opacity:0}to{opacity:1}}

  .masthead{animation:fadeIn 0.7s ease both}
  .statement{animation:riseIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.06s both}
  .body-copy{animation:riseIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.16s both}
  .colophon{animation:fadeIn 0.9s ease 0.3s both}
}

/* ---------------------------------------------------------------------------
   404
   --------------------------------------------------------------------------- */
.statement-small{
  font-family:var(--serif);
  font-weight:500;
  font-size:clamp(30px, 4.6vw, 58px);
  line-height:1.06;
  letter-spacing:-0.02em;
  max-width:18ch;
  text-wrap:balance;
}
.home-link{
  font-family:var(--serif);
  font-size:clamp(18px, 2.2vw, 24px);
  letter-spacing:-0.015em;
  align-self:flex-start;
  border-bottom:1px solid var(--hairline-strong);
  padding-bottom:3px;
  transition:color 0.25s ease, border-color 0.25s ease;
}
.home-link:hover{color:var(--accent);border-bottom-color:var(--accent)}
