/* ============================================================
   SINHVU.COM — DESIGN SYSTEM (Phase 1)
   ------------------------------------------------------------
   This is not a stylesheet for a website.
   This is a design system for an organization that operates.

   The system has three layers:
     1. TOKENS    — color, type, space, grid (the vocabulary)
     2. BASE      — element defaults (the grammar)
     3. COMPONENTS — sections, nav, lists, type roles (the syntax)

   Why a single file?
   Because Phase 1 is a foundation, and a foundation should be
   readable in one sitting. When the system grows, this file
   splits into /tokens.css /base.css /components.css.
   ============================================================ */


/* ============================================================
   1. TOKENS
   ============================================================
   Tokens are the vocabulary of the system.
   Every visual decision downstream MUST reference a token.
   Hardcoded values are bugs — they break the system's ability
   to be tuned globally.
   ============================================================ */

:root {

  /* --------------------------------------------------------
     COLOR
     --------------------------------------------------------
     Editorial systems use a narrow palette on purpose.
     Three families: ink (text), paper (background), accent (rare).
     Why warm grays? Cold neutrals feel corporate-tech.
     Warm neutrals feel considered, like a printed page.
     -------------------------------------------------------- */

  --ink-100:    #0c0c0a;   /* Primary text. Near-black, warm.   ~17:1 on paper */
  --ink-80:     #1c1c1a;   /* Headlines on light backgrounds.   ~14:1 on paper */
  --ink-60:     #4a4945;   /* Secondary text, captions.         ~8:1  on paper */
  --ink-40:     #6c6a64;   /* Tertiary, metadata, labels.       ~5:1  on paper
                              Darkened from #8a8780 in Phase 3 — old value was
                              ~3:1 which fails WCAG 2.1 AA for normal text
                              (4.5:1 needed). Diff strikethrough column and
                              method step numbers were the main offenders.
                              Visual hierarchy preserved: still lighter than
                              ink-60, still feels muted. To revert: change
                              back to #8a8780. */
  --ink-20:     #c9c5bc;   /* Hairlines, dividers — non-text, contrast exempt. */
  --ink-10:     #e6e1d6;   /* Soft surfaces. */

  --paper:      #f4f1ea;   /* Default background. Warm off-white. */
  --paper-soft: #ebe7dc;   /* Section contrast. */
  --paper-deep: #e0dccf;   /* Rare — used inside outputs panels. */

  --accent:     #b94a18;   /* Used <5 places on the entire site. */

  /* Inverted (for dark sections — used sparingly, e.g. CTA blocks) */
  --ink-inv:    #f4f1ea;
  --paper-inv:  #0c0c0a;


  /* --------------------------------------------------------
     TYPOGRAPHY
     --------------------------------------------------------
     One typeface, two weights. The system relies on size,
     spacing and rhythm — not weight or color — to express
     hierarchy. This is the editorial discipline.

     Inter Tight is chosen for: tight tracking at display sizes,
     full Vietnamese coverage, variable-weight efficiency,
     and a neutral voice that doesn't compete with content.
     -------------------------------------------------------- */

  --font-display: "Inter Tight", "Inter", "Helvetica Neue",
                  -apple-system, BlinkMacSystemFont, system-ui,
                  sans-serif;
  --font-body:    "Inter Tight", "Inter", "Helvetica Neue",
                  -apple-system, BlinkMacSystemFont, system-ui,
                  sans-serif;
  --font-mono:    ui-monospace, "SF Mono", "JetBrains Mono",
                  Menlo, Consolas, monospace;

  /* Weights — only two, intentionally.
     Editorial systems gain authority from restraint.
     Values match the static weights actually loaded from
     Inter Tight (400/500/600). Previous custom values (420/560)
     were rounded by the browser; this is the same look spelled
     correctly. */
  --w-regular:  400;
  --w-medium:   500;

  /* Type scale.
     The jumps between sizes are deliberate — no "almost the same"
     pairs. Each step has a role in the hierarchy. */
  --t-eyebrow: 12px;     /* Section numbers, eyebrows, metadata */
  --t-caption: 14px;     /* Captions, footnotes */
  --t-body:    17px;     /* Body copy */
  --t-lead:    21px;     /* Opening paragraphs, summary statements */
  --t-h4:      28px;     /* In-section subheads */
  --t-h3:      40px;     /* Sub-section titles */
  --t-h2:      64px;     /* Major section titles */
  --t-h1:      96px;     /* Page titles */
  --t-display: 140px;    /* Homepage hero only */

  /* Line-heights tuned per size.
     Display: tight (compressed feel).
     Body: open (long-form readability). */
  --lh-display:  0.92;
  --lh-heading:  1.04;
  --lh-lead:     1.32;
  --lh-body:     1.55;
  --lh-caption:  1.45;

  /* Letter-spacing.
     Tightens at display, opens at small caps for labels. */
  --tr-display:  -0.025em;
  --tr-heading:  -0.018em;
  --tr-body:     -0.005em;
  --tr-eyebrow:   0.12em;


  /* --------------------------------------------------------
     SPACE
     --------------------------------------------------------
     A modular scale, not a Tailwind-style 4px grid.
     Why? Because editorial rhythm needs distinct intervals,
     not 16 micro-steps. Use the closest token.
     -------------------------------------------------------- */

  --s-1:  4px;
  --s-2:  8px;
  --s-3:  16px;
  --s-4:  24px;
  --s-5:  40px;
  --s-6:  64px;
  --s-7:  96px;
  --s-8:  144px;
  --s-9:  200px;     /* Reserved for major section breaks */


  /* --------------------------------------------------------
     LAYOUT
     -------------------------------------------------------- */

  --max-w:        1440px;     /* Outer container ceiling. */
  --max-w-tight:  1100px;     /* For text-heavy sections — readability. */
  --max-w-narrow: 760px;      /* For long-form prose blocks. */
  --gutter:       24px;
  --gutter-lg:    40px;

  /* Grid */
  --cols:         12;


  /* --------------------------------------------------------
     MOTION
     --------------------------------------------------------
     One easing, one tempo family. No bouncy curves.
     The system should feel "quiet and intentional".
     -------------------------------------------------------- */

  --ease:        cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-quick:   240ms;
  --dur-base:    600ms;
  --dur-slow:    900ms;


  /* Border weights.
     Hairlines are 1px; dividers under headings are 1px;
     section dividers are 1px — the system uses ONE line weight. */
  --line:        1px solid var(--ink-20);
  --line-strong: 1px solid var(--ink-60);
}


/* ============================================================
   2. BASE
   ============================================================
   Element defaults. Reset is implicit — modern browsers are
   close enough that we just override what we want.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html {
  /* Anchor scroll behavior used for in-page navigation */
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-100);
  font-family: var(--font-body);
  font-size: var(--t-body);
  font-weight: var(--w-regular);
  line-height: var(--lh-body);
  letter-spacing: var(--tr-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Conservative feature-settings stack:
       kern  — kerning (universal, safe)
       liga  — standard ligatures (universal, safe)
       calt  — contextual alternates (universal, safe)
     lining-nums + proportional-nums match the editorial
     register (number heights line up with caps) and only affect
     digit glyphs, so Vietnamese diacritics are unaffected.
     ss01 / cv11 (stylistic + character variants) were tried in
     Phase 2 but pulled here in Phase B — without device-level
     visual QA on Vietnamese diacritic-heavy text, the safer
     decision is to ship Inter Tight's defaults. To re-enable:
     append "ss01", "cv11" to the font-feature-settings list. */
  font-feature-settings: "kern", "liga", "calt";
  font-variant-numeric: lining-nums proportional-nums;
}

/* text-wrap: balance for headlines avoids the "orphan word at the
   end of a 2-line headline" problem that otherwise has to be
   solved with manual <br>. text-wrap: pretty for paragraph copy
   reduces ragged right edges. Both are progressive enhancements;
   browsers without support fall back to default wrapping. */
h1, h2, h3, h4, h5, h6,
.display, .title-page, .title-section, .title-sub {
  text-wrap: balance;
}
.prose, .lead {
  text-wrap: pretty;
}

/* Reset margins on block elements — we control rhythm explicitly. */
h1, h2, h3, h4, h5, h6, p, ul, ol, figure, blockquote {
  margin: 0;
}

ul, ol { padding: 0; list-style: none; }

a {
  color: inherit;
  text-decoration: none;
  transition: opacity var(--dur-quick) var(--ease);
}

a:hover { opacity: 0.6; }

img, svg { display: block; max-width: 100%; height: auto; }

::selection {
  background: var(--ink-100);
  color: var(--paper);
}


/* ============================================================
   ACCESSIBILITY
   ============================================================
   Phase 3 additions — keyboard navigation and focus visibility.
   ============================================================ */

/* Skip-link — visually hidden until keyboard focused.
   Lets keyboard users jump past the nav directly to main
   content. Off-screen by default, slides into view on focus
   with the same easing the rest of the site uses.

   The site is small enough that this isn't strictly required,
   but it's a tiny win for keyboard users and doesn't add
   any visual cost. */
.skip-link {
  position: fixed;
  top: 0;
  left: var(--gutter);
  z-index: 100;
  background: var(--paper-inv);
  color: var(--ink-inv);
  padding: var(--s-3) var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-120%);
  transition: transform var(--dur-quick) var(--ease);
}

.skip-link:focus {
  transform: translateY(0);
  opacity: 1;
}

/* Focus-visible — only for keyboard, not mouse clicks.
   Default browser outline is functional but not editorial.
   Replace with the same hairline language used everywhere else:
   a 2px ink-100 outline with 4px offset.
   :focus-visible (not :focus) so mouse-clicked elements don't
   show the ring — that's the modern accessibility convention. */
:focus-visible {
  outline: 2px solid var(--ink-100);
  outline-offset: 4px;
}

.nav a:focus-visible,
.link-arrow:focus-visible {
  outline-offset: 6px;
}

.section--inverted :focus-visible {
  outline-color: var(--ink-inv);
}


/* ============================================================
   3. LAYOUT PRIMITIVES
   ============================================================ */

/* Outer container — every page-level section sits inside this.
   Why a class instead of margin: 0 auto on body? Because some
   sections (e.g. dark CTA blocks) need to span the viewport
   while keeping their inner content constrained. */
.container {
  max-width: var(--max-w);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

@media (min-width: 900px) {
  .container {
    padding-left: var(--gutter-lg);
    padding-right: var(--gutter-lg);
  }
}

.container--tight  { max-width: var(--max-w-tight); }
.container--narrow { max-width: var(--max-w-narrow); }

/* 12-column grid.
   Used inside sections for asymmetric editorial layouts.
   Avoid using grid as a "card row" — that defaults to symmetry. */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  column-gap: var(--gutter);
  row-gap: var(--s-5);
}

/* Section — the vertical rhythm primitive.
   Why such large padding? Because editorial whitespace IS
   the design. Without it, content reads as marketing. */
.section {
  padding-top: var(--s-8);
  padding-bottom: var(--s-8);
}

.section--lg {
  padding-top: var(--s-9);
  padding-bottom: var(--s-9);
}

.section--sm {
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
}

/* Modifier set used to break the uniform 144/144 rhythm.
   --tight   compresses both ends — used for "quiet pause" sections
             (Belief, Differentiation) so they don't feel like the
             same weight as the major content sections.
   --breathe expands the BOTTOM end only — used to push the
             following section further down the page, which gives
             a section the feel of a chapter break. */
.section--tight {
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
}

.section--breathe {
  padding-bottom: var(--s-9);
}

@media (max-width: 768px) {
  .section    { padding-top: var(--s-7); padding-bottom: var(--s-7); }
  .section--lg{ padding-top: var(--s-8); padding-bottom: var(--s-8); }
}

/* At very narrow widths, the rhythm has to shrink further or
   the page reads as 90% whitespace on a phone. The Phase 2
   modifiers (--tight, --breathe) need their own scaled-down
   values here too — otherwise they keep desktop spacing on
   mobile and the page still feels rhythmically wrong. */
@media (max-width: 500px) {
  .section          { padding-top: var(--s-6); padding-bottom: var(--s-6); }
  .section--lg      { padding-top: var(--s-7); padding-bottom: var(--s-7); }
  .section--sm      { padding-top: var(--s-5); padding-bottom: var(--s-5); }
  .section--tight   { padding-top: var(--s-5); padding-bottom: var(--s-5); }
  .section--breathe { padding-bottom: var(--s-7); }
  .section-head     { margin-bottom: var(--s-6); }
}

/* Inverted section — black on warm white reversed.
   Used for CTA, contact, and one block on home. */
.section--inverted {
  background: var(--paper-inv);
  color: var(--ink-inv);
}
.section--inverted .rule { background: var(--ink-40); }


/* ============================================================
   4. TYPOGRAPHY ROLES
   ============================================================
   These classes encode editorial roles, not sizes.
   We never style by size; we style by role.
   ============================================================ */

/* Eyebrow — section index, classification labels.
   Used as ".01 / WORLDVIEW" markers throughout.
   tabular-nums forces equal-width digits so that ".01", ".02",
   ".03" line up vertically when stacked — small detail, but it
   is the difference between "labels" and "system markers". */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  font-weight: var(--w-regular);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-60);
  display: inline-flex;
  gap: var(--s-3);
  align-items: center;
  font-variant-numeric: tabular-nums;
}

/* Display — homepage hero only. Never used elsewhere.
   Min lowered from 56→44px so the longest hero line
   ("structures that") doesn't overflow a 320px viewport.
   Tracking tightened from -0.025em → -0.028em — at 140px
   that's an extra ~0.4px of compression per character,
   which is the difference between "letters in a row" and
   "a single sculpted headline". em-based so the proportion
   holds at all sizes. */
.display {
  font-family: var(--font-display);
  font-size: clamp(44px, 10vw, var(--t-display));
  font-weight: var(--w-medium);
  line-height: var(--lh-display);
  letter-spacing: -0.028em;
  color: var(--ink-100);
  /* Same conservative feature-set as body — see Phase B note.
     The display is the most diacritic-prominent place on the
     site (the brand "Sinh Vũ" appears nowhere larger), so any
     uncertainty about glyph alternates is most visible here. */
  font-feature-settings: "kern", "liga", "calt";
  text-wrap: balance;
}

/* Page title — the H1 of every non-home page.
   Min lowered from 48→40px for the same reason. */
.title-page {
  font-family: var(--font-display);
  font-size: clamp(40px, 7vw, var(--t-h1));
  font-weight: var(--w-medium);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-display);
}

/* Section title — major section heading. */
.title-section {
  font-family: var(--font-display);
  font-size: clamp(36px, 5.5vw, var(--t-h2));
  font-weight: var(--w-medium);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
  max-width: 18ch;  /* Editorial wrap — long titles read as paragraphs. */
}

/* Subhead — within a section. */
.title-sub {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--w-medium);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
}

/* Lead — opening paragraph, summary statement. */
.lead {
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--ink-80);
  max-width: 36ch;
}

.lead--wide { max-width: 56ch; }

/* Body prose */
.prose p + p { margin-top: var(--s-4); }
.prose       { color: var(--ink-80); max-width: 56ch; }

/* Caption */
.caption {
  font-size: var(--t-caption);
  line-height: var(--lh-caption);
  color: var(--ink-60);
  font-variant-numeric: tabular-nums;
}


/* ============================================================
   5. COMPONENTS
   ============================================================ */

/* ----- Hairline rule -----
   Used as both a divider and a marker. The site uses this
   single horizontal rule everywhere instead of card borders,
   shadows, or backgrounds. */
.rule {
  height: 1px;
  background: var(--ink-20);
  width: 100%;
  border: 0;
}


/* ----- Top navigation -----
   The nav is intentionally quiet. It is a wayfinding tool,
   not a call-to-action. No logo lockup; the wordmark IS the logo. */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: var(--line);
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
}

.nav__brand {
  font-family: var(--font-display);
  font-weight: var(--w-medium);
  font-size: var(--t-body);
  letter-spacing: var(--tr-heading);
}

.nav__brand .dot { color: var(--accent); }

.nav__menu {
  display: flex;
  gap: var(--s-5);
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-60);
}

.nav__menu a[aria-current="page"] {
  color: var(--ink-100);
  position: relative;
}

.nav__menu a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: -6px;
  height: 1px;
  background: var(--ink-100);
}

/* On narrow viewports the nav stacks: brand on the first row,
   menu items on the second. We avoid a hamburger toggle — it
   imports UI clutter that the rest of the site refuses. The
   stacked layout keeps all six items reachable, with .flex-wrap
   as a safety net when items still don't fit on a single row. */
@media (max-width: 600px) {
  .nav__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-3);
    padding-top: var(--s-3);
    padding-bottom: var(--s-3);
  }
  .nav__menu {
    gap: var(--s-3);
    flex-wrap: wrap;
    width: 100%;
  }
}


/* ----- Hero block -----
   The hero is a worldview statement, not a marketing headline.
   Note: the layout is asymmetric — the lead sits in cols 7-12,
   forcing the reader's eye to track from a long display line
   to a tighter, denser block. This is editorial pacing.
   Top padding tightened from --s-9 → --s-7 because the new
   .hero__head preamble already pushes the display down a row;
   the previous spacing left the display floating in space. */
.hero {
  padding-top: var(--s-6);
  padding-bottom: var(--s-7);
}

/* Preamble row — small status line above the display.
   Anchors the page: studio name, location, year. Reads as
   datestamp on an editorial publication, not as a marketing
   strapline. */
.hero__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: var(--line);
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-7);
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-60);
  font-variant-numeric: tabular-nums;
  gap: var(--s-3);
  flex-wrap: wrap;
}

.hero__head .hero__head-right {
  color: var(--ink-40);
}

.hero__display { margin-bottom: var(--s-7); }

.hero__meta {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  align-items: end;
  border-top: var(--line);
  padding-top: var(--s-4);
}

.hero__meta-left  {
  grid-column: 1 / span 5;
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-60);
}

.hero__meta-right {
  grid-column: 7 / span 6;
}

@media (max-width: 800px) {
  .hero__meta-left, .hero__meta-right {
    grid-column: 1 / -1;
  }
  .hero__meta-left { margin-bottom: var(--s-3); }
}

/* ----- Hero — mobile polish ----------------------------------
   Three issues addressed at <=600px:

   (1) The hardcoded <br> elements in .hero__display force the
       longest line ("structures that") onto a single row. At
       widths under ~340px that line overflows even with the
       40px display floor. Hiding the breaks lets the text wrap
       naturally and text-wrap:balance distributes the words.
   (2) flex + justify-content: space-between + flex-wrap on a
       narrow viewport produces a single item floated to the
       right edge of the second line — visually broken. Switch
       to a column stack at <=600px instead.
   (3) The 96px gap between hero__head, hero__display and
       hero__meta dominates the small viewport. Tighten to 64px.
   ----------------------------------------------------------- */
@media (max-width: 600px) {
  .hero__head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-1);
    margin-bottom: var(--s-6);
  }
  .hero__display {
    margin-bottom: var(--s-6);
  }
  .hero__display br { display: none; }
}


/* ----- Section header -----
   Every section opens with a numbered eyebrow and a title.
   The number reinforces "this is part of a system, not a list
   of services". */
.section-head {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  border-top: var(--line);
  padding-top: var(--s-4);
  margin-bottom: var(--s-7);
}

.section-head__index {
  grid-column: 1 / span 3;
}

.section-head__title {
  grid-column: 4 / span 8;
}

.section-head__lead {
  grid-column: 4 / span 8;
  margin-top: var(--s-4);
}

/* Right-aligned modifier.
   Pushes the title and lead into cols 7-12 instead of 4-12,
   creating a deliberate void in the middle of the page.
   Used once per long page to break the visual cadence of
   eyebrow-then-wide-block. */
.section-head--right .section-head__title { grid-column: 7 / span 6; }
.section-head--right .section-head__lead  { grid-column: 7 / span 6; }

@media (max-width: 800px) {
  .section-head__index,
  .section-head__title,
  .section-head__lead,
  .section-head--right .section-head__title,
  .section-head--right .section-head__lead {
    grid-column: 1 / -1;
  }
  .section-head__title { margin-top: var(--s-3); }
}


/* ----- System list -----
   Used on Home (Systems we build) and across pages.
   Each row is a numbered editorial entry — no card, no shadow,
   only a top hairline and a wide wrap. The row IS the surface. */
.systems {
  border-top: var(--line);
}

.systems__row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  padding: var(--s-6) 0;
  border-bottom: var(--line);
  align-items: start;
}

.systems__num {
  grid-column: 1 / span 1;
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  color: var(--ink-40);
  padding-top: 6px;  /* Optical alignment with title baseline. */
}

.systems__title {
  grid-column: 2 / span 5;
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--w-medium);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
}

.systems__body {
  grid-column: 8 / span 5;
  color: var(--ink-60);
}

@media (max-width: 900px) {
  .systems__row { padding: var(--s-5) 0; }
  .systems__num   { grid-column: 1 / -1; margin-bottom: var(--s-2); }
  .systems__title { grid-column: 1 / -1; margin-bottom: var(--s-3); font-size: var(--t-h4); }
  .systems__body  { grid-column: 1 / -1; }
}


/* ----- Method steps -----
   "Statement flow" pattern.
   ------------------------------------------------------------
   Earlier this section used the same num | title | body grid
   as .systems, which made Systems and Method look identical to
   the eye despite expressing different ideas. Now the title
   and body are merged into a single .method__statement
   paragraph: the title is the strong opening sentence, the
   body is its continuation. The number sits in a fixed-width
   marginalium on the left.
   This produces a visibly different rhythm from .systems
   (which is two stacked columns) and reinforces that Method
   is a sequence of arguments, not a list of capabilities. */
.method {
  border-top: var(--line);
}

.method__step {
  display: grid;
  grid-template-columns: 88px 1fr;
  column-gap: var(--s-5);
  padding: var(--s-6) 0;
  border-bottom: var(--line);
  align-items: baseline;
}

.method__num {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  font-weight: var(--w-regular);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-40);
  font-variant-numeric: tabular-nums;
}

.method__statement {
  max-width: 64ch;
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--ink-60);
  text-wrap: pretty;
}

.method__title {
  font-family: var(--font-display);
  font-weight: var(--w-medium);
  color: var(--ink-100);
  letter-spacing: var(--tr-heading);
  margin-right: var(--s-2);
}

@media (max-width: 700px) {
  .method__step {
    grid-template-columns: 1fr;
    row-gap: var(--s-3);
    padding: var(--s-5) 0;
  }
}


/* ----- Output panels -----
   Outputs are presented as ARTIFACT blocks: a label, a measure,
   a one-line context. NOT case-study cards — the brief is
   explicit that we do not present work as a portfolio gallery. */
.outputs {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  row-gap: var(--s-6);
  border-top: var(--line);
  padding-top: var(--s-6);
}

.output {
  padding: var(--s-5) 0;
  border-bottom: var(--line);
}

.output:nth-child(1) { grid-column: 1 / span 7; }
.output:nth-child(2) { grid-column: 8 / span 5; }
.output:nth-child(3) { grid-column: 1 / span 5; }
.output:nth-child(4) { grid-column: 6 / span 7; }

.output__label {
  font-family: var(--font-mono);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--ink-60);
  margin-bottom: var(--s-3);
}

.output__measure {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--w-medium);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
  margin-bottom: var(--s-3);
  max-width: 18ch;
}

.output__context {
  color: var(--ink-60);
  max-width: 48ch;
}

@media (max-width: 900px) {
  .output:nth-child(n) { grid-column: 1 / -1; }
}


/* ----- Differentiation block -----
   Three-column comparison: how the typical model fails,
   how Sinh Vũ does it, why the difference matters. */
.diff {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  border-top: var(--line);
}

.diff__row {
  display: contents;  /* The grid container handles columns. */
}

.diff__row > * {
  border-bottom: var(--line);
  padding: var(--s-5) 0;
}

.diff__label   { grid-column: 1 / span 3; color: var(--ink-40);
                  font-family: var(--font-mono);
                  font-size: var(--t-eyebrow);
                  letter-spacing: var(--tr-eyebrow);
                  text-transform: uppercase; }
.diff__typical { grid-column: 4 / span 4; color: var(--ink-40);
                  text-decoration: line-through;
                  text-decoration-color: var(--ink-40); }
.diff__sinhvu  { grid-column: 8 / span 5; color: var(--ink-100); }

@media (max-width: 900px) {
  .diff__label, .diff__typical, .diff__sinhvu { grid-column: 1 / -1; }
  .diff__label   { padding-bottom: var(--s-2); border-bottom: 0; }
  .diff__typical { padding-top: 0; padding-bottom: var(--s-2); border-bottom: 0; }
  .diff__sinhvu  { padding-top: 0; }
}


/* ----- CTA / Invitation -----
   The CTA is calm. No loud button — a hairline-bordered
   text link with a long underline and a small arrow glyph. */
.cta-block {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  align-items: end;
  border-top: var(--line);
  padding-top: var(--s-6);
}

.cta-block__lead   { grid-column: 1 / span 7; }
.cta-block__action { grid-column: 9 / span 4; text-align: right; }

@media (max-width: 800px) {
  .cta-block__lead, .cta-block__action {
    grid-column: 1 / -1; text-align: left;
  }
  .cta-block__action { margin-top: var(--s-4); }
}

.link-arrow {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-2);
  font-family: var(--font-display);
  font-size: var(--t-h4);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-heading);
  border-bottom: 1px solid var(--ink-100);
  padding-bottom: 4px;
  transition: gap var(--dur-quick) var(--ease);
}

.link-arrow:hover {
  opacity: 1;
  gap: var(--s-3);
}

.link-arrow .arrow {
  font-family: var(--font-mono);
  font-weight: var(--w-regular);
}


/* ----- Footer -----
   Footer is a final marker. Not a sitemap dump. */
.footer {
  border-top: var(--line);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  font-family: var(--font-mono);
  font-size: var(--t-caption);
  color: var(--ink-60);
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
}

.footer__inner {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  align-items: center;
}

.footer__brand   { grid-column: 1 / span 4; color: var(--ink-100); }
.footer__center  { grid-column: 5 / span 4; text-align: center; }
.footer__right   { grid-column: 9 / span 4; text-align: right; }

/* Footer collapse breakpoint moved from 700→900.
   At 700–900px the center cell ("A studio for systems that
   operate", ~288px at 14px mono) didn't fit its 4-col allocation
   (~200px) and wrapped to two lines mid-row, breaking the
   single-line masthead feel of the footer. Stacking earlier
   keeps each line on its own row, which is the intended
   editorial register on tablet portrait and below. */
@media (max-width: 900px) {
  .footer__brand, .footer__center, .footer__right {
    grid-column: 1 / -1; text-align: left;
  }
  .footer__center, .footer__right { margin-top: var(--s-2); }
}


/* ----- Row primitives -----
   Two patterns recurring across /work, /contact, /knowledge.
   Defined as proper components so the layout collapses cleanly
   on narrow viewports — previously these were inline grid-column
   styles in the HTML, which kept their desktop layout on phones
   and produced a 3-column 60-character text squeeze. */

/* row-meta — a label column (cols 1-3) + content column (cols 4-12).
   Used on /work for project entries and on /contact for inquiry rows. */
.row-meta {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
}

.row-meta__label   { grid-column: 1 / span 3; }
.row-meta__content { grid-column: 4 / span 9; }

@media (max-width: 800px) {
  .row-meta__label,
  .row-meta__content { grid-column: 1 / -1; }
  .row-meta__label   { margin-bottom: var(--s-3); }
}

/* article-row — date + category + title.
   Used on /knowledge for the article index. The title carries
   the meaning, so it gets the wide column. */
.article-row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  align-items: baseline;
}

.article-row__date  { grid-column: 1 / span 2; }
.article-row__cat   { grid-column: 3 / span 2; }
.article-row__title { grid-column: 5 / span 8; }

@media (max-width: 800px) {
  .article-row__date,
  .article-row__cat,
  .article-row__title { grid-column: 1 / -1; }
  .article-row__title { margin-top: var(--s-2); }
}


/* ============================================================
   6. MOTION
   ============================================================
   Subtle by design. Fade + 24px translateY. No parallax.
   Honors prefers-reduced-motion.
   ============================================================ */

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
  will-change: opacity, transform;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  html { scroll-behavior: auto; }
}


/* ============================================================
   7. UTILITIES
   ============================================================
   Reserved set. Add only when a need recurs three times.
   ============================================================ */

.text-quiet   { color: var(--ink-60); }
.text-muted   { color: var(--ink-40); }
.text-right   { text-align: right; }
.no-wrap      { white-space: nowrap; }
.mt-4         { margin-top: var(--s-4); }
.mt-5         { margin-top: var(--s-5); }
.mt-6         { margin-top: var(--s-6); }
.mt-7         { margin-top: var(--s-7); }


/* ============================================================
   PRINT
   ============================================================
   Editorial discipline extends to the printed page.
   Kept minimal: the site already uses paper-on-ink which prints
   reasonably with browser defaults, but a few targeted overrides
   make the printout feel like a publication rather than a web
   page screenshot.

   - Hide nav, skip-link, footer (they're navigational; useless on paper)
   - Pure black on white for ink savings
   - Reveal-state always visible (no progressive reveal in print)
   - URL appears after every external link so the reader can
     follow citations on paper
   - No URL after on-page anchors or mailto links (those are noise)
   - Tighter section padding — print pages have less generous
     vertical real estate than screens
   ============================================================ */
@media print {
  body { background: white; color: black; }

  .nav, .skip-link, .footer { display: none; }

  /* Override the IntersectionObserver-driven reveal.
     If the page prints before scroll, .reveal stays invisible. */
  .reveal {
    opacity: 1 !important;
    transform: none !important;
  }

  /* Show URLs after external links (for paper readers). */
  a[href]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    color: #555;
  }
  /* Don't show URL for on-page anchors, mailto, or javascript. */
  a[href^="#"]::after,
  a[href^="mailto:"]::after,
  a[href^="javascript:"]::after { content: ""; }

  /* Tighter rhythm for print (don't waste paper). */
  .section, .section--lg, .section--tight, .section--breathe {
    padding-top: 24pt;
    padding-bottom: 24pt;
  }

  /* Don't break inside a method step or a system row mid-statement. */
  .method__step, .systems__row, .output {
    break-inside: avoid;
  }
}


/* ============================================================
   END OF FILE
   ============================================================
   When this file exceeds ~800 lines, split into:
     /css/tokens.css
     /css/base.css
     /css/components.css
   And import via @import in a single sinhvu.css entry point.
   ============================================================ */
