/* I AM RATAN — house system, v1 language.

   This is the vocabulary of the approved home page (index.html), extracted so the
   long-form pages share it instead of each carrying a copy. index.html keeps its
   own inline styles until the polish pass migrates it here; the tokens below are
   byte-identical to its own, so that migration is a delete, not a redesign.

   One rule this file exists to hold: the twenty-five garment colours are the only
   chroma in the system. The chrome is a workroom. The cloth is the colour. */

:root{
  --room:#EDE9E0;           /* bone — the house ground                        */
  --under:#E3DFD4;          /* one step under, for alternating bands          */
  --deep:#DAD5C8;           /* the footer floor                               */
  --ink:#1A1C1E;            /* 14.1:1 on bone                                 */
  --navy:#1C254A;
  --card:#B9A882;           /* stiff manila pattern card — surfaces only      */
  --claret:#6B2F3A;         /* one accent, a FILL and never text on the room  */

  /* .70 is the floor on bone: below it muted text drops under 4.5:1 */
  --muted:rgba(26,28,30,.70);
  --hair:rgba(26,28,30,.20);

  --sans:'Anek Latin',system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,monospace;

  /* ---------- the spacing scale ----------
     Measured before writing it: the site was using 144 distinct spacing values,
     84 of them one-off clamp() expressions invented at the point of use. That
     is why the spacing never felt settled — every section was picking its own
     rhythm, so no amount of fixing one block made the next one agree.

     Nine steps, and nothing else. Roughly a 1.5x ratio, so two steps apart is
     always clearly different and one step apart is a nudge. The last two are
     fluid because section rhythm should breathe with the screen; the small ones
     are fixed because 8px is 8px on any device.

       --s0   4px   inside a control
       --s1   8px   label to its own field
       --s2  12px   between lines of a group
       --s3  16px   between fields
       --s4  24px   between small blocks
       --s5  32px   between blocks
       --s6  48px   between groups
       --sy  40-64  within a section
       --sz  56-96  between sections

     Run iar-lab/space.py to see what still does not use them. */
  --s0:.25rem; --s1:.5rem; --s2:.75rem; --s3:1rem;
  --s4:1.5rem; --s5:2rem;  --s6:3rem;
  /* The two fluid steps. The floors were the bug, not the flatness: at 40px and
     56px a 375px phone was being handed section padding sized for a tablet, and
     because 5vw/7vw do not reach those floors until an 800px viewport, EVERY
     phone got the same tablet-sized gap. That is what made the site read as
     over-spaced on a phone however often the numbers were nudged.
     Floors down about a quarter, coefficients up so they start growing around
     500px instead of 800px, and both still land on the same 64px and 96px once
     there is a desktop to fill — so nothing above 1100px moves at all. */
  --sy:clamp(1.875rem,6vw,4rem);
  --sz:clamp(2.625rem,9vw,6rem);

  --gut:clamp(1.1rem,4vw,4.5rem);
  --max:1500px;
  /* The height of the fixed bar, derived from the mark rather than guessed at:
     two rems of bar padding, the mark's own height at this width, and the
     hairline. Anything that begins at the top of the page has to clear it or
     the bar sits on top of it — which is how the hero kept losing heads. */
  /* The mark's width, written once. It used to be typed twice — here and on
     .mk — and the two drifted apart the moment either was nudged, which is how
     the bar ended up taller than the thing it was measuring. The floor is what
     a phone gets and is deliberately unchanged; only the ceiling came down,
     from 128px, because past about 1350px the mark stopped growing WITH the
     page and simply sat there being large. */
  --mkw:clamp(92px,5.6vw,108px);
  --bar:calc(2rem + 1px + var(--mkw) * 620 / 1430);
  /* What the first block on a page needs above it. Not a spacing choice — it is
     the bar's height plus one step of air — so it gets a name instead of a
     number. Typed as a number it was 6.5rem, which cleared the bar on a desktop
     and hid the eyebrow underneath it on a phone, because the bar grows with the
     mark and a fixed 6.5rem does not. */
  --clear:calc(var(--bar) + var(--s4));
  /* a damped pendulum, not a UI curve: cloth has mass */
  --swing:cubic-bezier(.2,.9,.25,1);
  --settle:cubic-bezier(.16,1,.3,1);
}

/* ---------- grounds ----------
   The client's own references (100Hands, 11.11) both stand on white. The house
   was built on near-black. Switching is a token change and nothing else, because
   the twenty-five garment colours were never separated by the ground in the
   first place — measured, the best flat ground still leaves ten of them under
   3:1, so separation has always come from the computed per-swatch edge. That
   edge re-runs against whatever ground is set.

   Measured for each ground below: ink, muted text, and the hairline.
     room   ink 15.49  muted(.64) 6.81
     bone   ink 14.11  muted(.70) 5.75
     white  ink 17.09  muted(.68) 6.30
   All clear 4.5:1. Set with <html data-ground="bone">. */
:root[data-ground="dark"]{
  --room:#101214; --under:#0D0F11; --deep:#0A0B0C; --ink:#EDE9E0;
  --muted:rgba(237,233,224,.64); --hair:rgba(237,233,224,.16);
}
:root[data-ground="white"]{
  --room:#FFFFFF; --under:#F5F5F5; --deep:#EDEDED; --ink:#1A1C1E;
  --muted:rgba(26,28,30,.68); --hair:rgba(26,28,30,.17);
}
/* A plate is a photograph under a dark scrim, so its type stays chalk on every
   ground — dark ink over a darkened image is the one combination that fails. */
.plate-copy{color:#EDE9E0}
.plate-copy .muted{color:rgba(237,233,224,.64)}
.plate-copy .rule{background:rgba(237,233,224,.22)}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  margin:0;background:var(--room);color:var(--ink);
  font-family:var(--sans);font-size:1rem;line-height:1.62;font-weight:300;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
}
a{color:inherit;text-decoration:none}
img{display:block;max-width:100%}
button,input,select,textarea{font:inherit;color:inherit}
/* The rest of the button reset used to live inline in index.html and a handful
   of others, which meant any NEW page got grey system buttons with a bevel —
   found exactly that way on the bespoke drafts. It belongs in the shared sheet.
   Safe to make global: every button in the house draws its own border and
   ground, so there is nothing here relying on the default. */
button{background:none;border:0;padding:0;cursor:pointer;text-align:inherit}

/* Every page cross-fades into the next, so the site reads as one continuous
   room rather than a stack of documents. This used to live only on the home
   page — but a transition needs to be declared on BOTH pages of a navigation,
   so in the shared sheet it actually happens everywhere. */
@view-transition{navigation:auto}
::view-transition-old(root),::view-transition-new(root){animation-duration:.5s}
@media(prefers-reduced-motion:reduce){
  ::view-transition-old(root),::view-transition-new(root){animation:none}
}

/* Carried but not painted. For a heading a page needs in its document — for a
   screen reader working through the outline, and for the result Google prints —
   but which the design has no room to show. Not display:none: that removes it
   from the accessibility tree too, which is the opposite of the point. */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* The first tab stop on every page. Invisible until a keyboard asks for it,
   then it sits above the fixed bar. */
.skip{position:fixed;top:var(--s2);left:var(--s2);z-index:99;
  background:var(--ink);color:var(--room);padding:var(--s2) var(--s3);
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.14em;
  text-transform:uppercase;transform:translateY(-200%)}
.skip:focus-visible{transform:none}
:focus-visible{outline:2px solid currentColor;outline-offset:3px}
.wrap{max-width:var(--max);margin-inline:auto;padding-inline:var(--gut)}

/* ---------- type ----------
   One Indian-drawn family carries display and text. A house that made European
   luxury anonymously for twenty years does not wear a European editorial serif. */
.fig{font-family:var(--mono);font-variant-numeric:tabular-nums}
.label{font-family:var(--mono);font-size:.625rem;letter-spacing:.2em;
  text-transform:uppercase;line-height:1.5}
.muted{color:var(--muted)}
.display{font-weight:200;font-size:clamp(2.7rem,7vw,5.4rem);line-height:.95;
  letter-spacing:-.035em;margin:0;text-wrap:balance}
.h1{font-weight:250;font-size:clamp(1.9rem,4vw,3rem);line-height:1.05;
  letter-spacing:-.028em;margin:0;text-wrap:balance}
.h2{font-weight:300;font-size:clamp(1.35rem,2.2vw,1.85rem);line-height:1.15;
  letter-spacing:-.022em;margin:0;text-wrap:balance}
.lede{font-weight:250;font-size:clamp(1.05rem,1.5vw,1.3rem);line-height:1.5;
  margin:0;max-width:42ch}
/* long-form measure: 62ch is the limit before the eye loses the line return */
.prose p{margin:0 0 1.15em;max-width:62ch}
.prose p:last-child{margin-bottom:0}
.prose--wide p{max-width:70ch}
.prose em{font-style:normal;color:var(--muted)}

/* ---------- rules and reveals ---------- */
.rule{height:1px;background:var(--hair);width:100%}
.snap{transform:scaleX(0);transform-origin:left}
.snap.in{transform:scaleX(1);transition:transform .42s var(--swing)}
.rise{opacity:0;transform:translateY(14px)}
.rise.in{opacity:1;transform:none;
  transition:opacity .7s var(--settle),transform .7s var(--settle)}

/* ---------- header ----------
   A solid bar in the house ground, not a scrim. The old version faded out over
   whatever was beneath it, which meant the ink had to keep switching between
   dark and chalk and the nav sat at whatever contrast the photograph happened
   to give it.

   Solid also means the walk-in film always works: it has bone baked into its
   background, so on a translucent header over dark media it showed as a bone
   rectangle — which is why mark.js used to skip it on any non-bone ground.
   Against a bone bar it simply blends.                                       */
/* A grid, not space-between. With space-between the nav's position depended on
   whatever the third slot held — "Hyderabad" on most pages, nothing on phones
   (display:none), the Customize count on product — so the menu sat somewhere
   different on every tab. Fixed columns pin the nav to the centre regardless
   of what its neighbours are doing. */
.top{position:fixed;inset:0 0 auto 0;z-index:50;display:grid;
  grid-template-columns:1fr max-content 1fr;align-items:center;gap:var(--s3);
  /* The ground spans the window; the CONTENTS stop at --max, like every other
     block on the site. The bar was the one thing that ignored the container, so
     on a wide screen the mark sat hard against the left edge and Hyderabad hard
     against the right, with 600px of nothing between each of them and the menu.
     Extra padding, not a max-width, because the background and the hairline
     still have to reach both edges. */
  padding:var(--s3) max(var(--gut),(100% - var(--max)) / 2);
  background:var(--room);color:var(--ink);
  border-bottom:1px solid var(--hair)}
.top>:first-child{justify-self:start}
.top>:last-child{justify-self:end}
.mark{width:36px;aspect-ratio:716/478;display:block;background:currentColor;
  -webkit-mask:url('mark-badger.png') no-repeat center/contain;
  mask:url('mark-badger.png') no-repeat center/contain}

/* ---------- the mark, in three layers ----------
   The monogram was one flat PNG. It is now split by connected-component analysis
   into letterforms, badger body and badger head, each exported as an alpha mask
   so every layer still paints in currentColor and follows the ground.

   The badger in the finished mark is already looking back over its shoulder —
   that IS the logo. So the animation earns that pose rather than inventing one:
   the badger walks in with its head forward, stops, and turns to look back.
   Head and body overlap by twelve pixels so the neck never opens a seam. */
.mk{position:relative;display:block;width:var(--mkw);
  aspect-ratio:1430/620;color:inherit}
/* Only the three masked layers take the fill. .mk-badger is a positioning
   wrapper — giving it currentColor with no mask painted a solid block over the
   whole mark, which is exactly what it did the first time. */
.mk-letters,.mk-body,.mk-head{position:absolute;inset:0;display:block;
  background:currentColor;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain}
.mk-badger{background:none}
.mk-letters{-webkit-mask-image:url('mark-letters.png');mask-image:url('mark-letters.png')}
.mk-body{-webkit-mask-image:url('mark-body.png');mask-image:url('mark-body.png')}
.mk-head{-webkit-mask-image:url('mark-head.png');mask-image:url('mark-head.png');
  transform-origin:73.6% 50.2%}

.mk-badger{position:absolute;inset:0}

/* ---------- the clips ----------
   The walk-in and the three reactions are real film — generated cycles with an
   articulated gait, which a CSS transform cannot produce. They are pinned at
   both ends to frames composited from these same masked layers, so the
   letterforms never drift, and each one crossfades back to the mask mark while
   the badger is still. The resting logo is always the true one.

   They are animated IMAGES with an alpha channel, not video. Video autoplay is
   refused outright by iOS in Low Power Mode, and the clips used to carry the
   house bone baked into their background at rgb(231,229,219) — against the
   header's #EDE9E0 that showed as a pale rectangle pasted in behind the logo.
   With the ground keyed out there is nothing left to match.

   object-fit:contain, and the clips are cropped to the mark's own 1430:620, so
   the logo inside them fills the frame the way the mask does. Before that fit
   the film's logo sat at 93% width against the mask's 100% and the handover at
   the end of the walk visibly jumped in scale.                                */
.mk-clip{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  pointer-events:none}
.mk--clip .mk-letters,.mk--clip .mk-badger{opacity:0}
.mk-letters,.mk-badger{transition:opacity .3s linear}


/* The lingering glance on the true mask mark, once the entry is done — the
   breathing between the filmed reactions rather than a reaction itself.
   It ran on a 13s loop, which is four and a half glances a minute: often
   enough that the eye starts watching the logo instead of the page. At 34s it
   is something you catch rather than something you notice. The percentages are
   retuned with it so the glance itself still takes about three seconds; left
   alone they would have stretched it to nine. */
.mk--idle .mk-head{animation:mk-glance 34s var(--settle) infinite}
@keyframes mk-glance{
  0%,89%{transform:rotate(0)}
  93%,96%{transform:rotate(12deg)}
  100%{transform:rotate(0)}
}
.markwrap{-webkit-tap-highlight-color:transparent}

@media(prefers-reduced-motion:reduce){
  .mk-letters,.mk-badger,.mk-head,.mk-body,.mk-clip{animation:none!important;
    transition:none!important}
  .mk-head{transform:rotate(0)}
  .mk-clip{display:none}
}
.nav{display:flex;gap:var(--s5)}
.nav a{position:relative;padding-block:var(--s0)}
.nav a::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:left;
  transition:transform .38s var(--swing)}
.nav a:hover::after,.nav a[aria-current]::after{transform:scaleX(1)}
/* ---------- the menu on a phone ----------
   Four links, the mark and the town were all being squeezed onto 375px by
   shrinking the type to 9px and the gaps to 8px. That is not a menu, it is a
   row of marks you can neither read nor reliably hit — the links were under
   the 24px minimum a thumb needs in both directions.

   So on a phone the links come out of the bar and into a panel. The bar keeps
   the mark and a button; the panel holds full-size links with room to press.

   Every rule here is behind [data-nav] on <html>, which nav.js sets once
   it has built the button. Without JavaScript the attribute never appears, the
   old inline row stays, and a visitor still has working navigation — a menu
   that depends on a script to exist is a menu that can vanish. */
/* 1024, not 760. The inline row is 10px mono at EVERY width — that is the
   house's label bar and it is right under a mouse, but its links are 23px tall,
   under the 24px a finger needs. Measured at 820px, which is a tablet in
   landscape and a small laptop window: still the inline row, still 10px, still
   23px targets. The drawer now covers every touch-sized viewport and hands the
   row back only where there is a pointer to use it. */
@media(max-width:1024px){
  /* Below 1025px the bar held two columns but three in-flow items: the mark,
     the account block and the menu button. The nav is the drawer and is fixed,
     so it is not one of them. The button wrapped to a second row and the bar
     stood 133px tall instead of 77.

     A counted number of columns is what broke, so the fix does not count: the
     mark takes the one 1fr track and everything after it makes its own column
     on the same row, however many end up there. The account block is emptied
     into the drawer at this width and is removed rather than left holding a
     column and a gap open. */
  [data-nav] .top{grid-template-columns:1fr;grid-auto-flow:column;
    grid-auto-columns:max-content;gap:var(--s3)}
  [data-nav] .top-end:not(:has(*)){display:none}

  .navbtn{display:inline-flex;flex-direction:column;justify-content:center;
    /* the gap between the three bars is the drawn glyph's own geometry, not
       air between elements, so it rides the type rather than the scale */
    gap:.3125em;width:2.75rem;height:2.75rem;align-items:flex-end;
    margin-right:calc(var(--s2) * -1);cursor:pointer}
  .navbtn i{display:block;height:1px;width:22px;background:currentColor;
    transition:transform .4s var(--swing),opacity .25s}
  .navbtn i:nth-child(2){width:15px}
  [data-nav="open"] .navbtn i:nth-child(1){transform:translateY(6px) rotate(45deg)}
  [data-nav="open"] .navbtn i:nth-child(2){opacity:0}
  [data-nav="open"] .navbtn i:nth-child(3){transform:translateY(-6px) rotate(-45deg);width:22px}

  /* the panel. Fixed, so it is never clipped by the bar's own stacking. */
  [data-nav] .nav{position:fixed;inset:0 0 0 auto;width:min(20rem,82vw);
    z-index:60;display:grid;align-content:start;gap:0;
    padding:calc(var(--bar) + var(--s5)) var(--gut) var(--sy);
    background:var(--room);border-left:1px solid var(--hair);
    transform:translateX(100%);transition:transform .42s var(--settle);
    overscroll-behavior:contain}
  [data-nav="open"] .nav{transform:none}

  /* full-size links with a real target: 3.25rem is 52px, comfortably over the
     24px minimum, and each one keeps its own hairline so the list reads as a
     list rather than a stack of words */
  [data-nav] .nav a{font-size:1.125rem;letter-spacing:-.01em;
    text-transform:none;font-family:var(--sans);font-weight:300;
    min-height:3.25rem;display:flex;align-items:center;
    border-bottom:1px solid var(--hair);padding-block:0}
  [data-nav] .nav a::after{display:none}
  [data-nav] .nav a[aria-current]{font-weight:400}

  /* 40, under the bar's 50. The panel is a child of the header, so its own
     z-index:60 is capped by the header's 50 — a veil at 55 sat OVER the
     panel and greyed the menu it was meant to set apart. Below the bar,
     the veil dims the page and leaves both the bar and the panel crisp. */
  .navveil{position:fixed;inset:0;z-index:40;background:rgba(9,10,12,.44);
    opacity:0;pointer-events:none;transition:opacity .42s var(--settle)}
  [data-nav="open"] .navveil{opacity:1;pointer-events:auto}
}
@media(min-width:1025px){.navbtn,.navveil{display:none}}
@media(prefers-reduced-motion:reduce){
  [data-nav] .nav,.navveil,.navbtn i{transition:none}
}

@media(max-width:640px){
  .top{gap:var(--s1)}
}

/* ---------- bands ----------
   The rhythm is driven by WIDTH, not height. It used to be 9vh, which has it
   backwards: a phone has the tallest viewport and the least room to spare, so
   it was being given 81px of padding top and bottom while a laptop got 72px.
   Between two full-bleed frames that came to 162px of empty ground per picture.
   Off width, a phone gets 48px and a wide screen still gets its 104px.        */
.band{padding:var(--sz) 0}
.band--tight{padding:var(--sy) 0}
.band--under{background:var(--under)}
.band--card{background:var(--card);color:#0C0B0A}
.band--card .muted{color:rgba(12,11,10,.7)}
.band--card .rule{background:rgba(12,11,10,.2)}
.band--card .prose em{color:rgba(12,11,10,.7)}

/* ---------- calls to action ---------- */
.cta{display:inline-block;border:1px solid currentColor;padding:var(--s2) var(--s5);
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.18em;
  text-transform:uppercase;cursor:pointer;background:none;
  transition:background-color .4s var(--settle),color .4s var(--settle)}
.cta:hover{background:var(--ink);color:var(--room)}
.band--card .cta:hover{background:#0C0B0A;color:var(--card)}
.cta--fill{background:var(--claret);border-color:var(--claret);color:#EDE9E0}
.cta--fill:hover{background:var(--ink);border-color:var(--ink);color:var(--room)}

/* ---------- figures ---------- */
.shot{position:relative;display:block;overflow:hidden;margin:0;
  aspect-ratio:4/3;background:#191C1F}
.shot img{width:100%;height:100%;object-fit:cover;object-position:center 16%;
  transition:transform 1.2s var(--settle)}
.shot--tall{aspect-ratio:4/5}
.shot--square{aspect-ratio:1/1}
a.shot:hover img{transform:scale(1.03)}
.shot figcaption{position:absolute;left:0;right:0;bottom:0;padding:var(--s3) var(--s3);
  font-family:var(--mono);font-size:.625rem;letter-spacing:.14em;
  text-transform:uppercase;color:#EDE9E0;
  background:linear-gradient(to top,rgba(12,13,15,.72),transparent)}

/* full-bleed film or plate with copy sitting in its lower gutter */
.plate{position:relative;min-height:62svh;display:grid;align-items:end;
  overflow:hidden;isolation:isolate;background:#191C1F}
.plate--tall{min-height:100svh}
/* <picture> counts as the child, not the <img> inside it, so a plate that uses
   art direction lost its absolute fill and collapsed. The picture is made the
   positioned box and the image fills it. */
.plate>picture{position:absolute;inset:0;display:block}
.plate>picture>img{width:100%;height:100%;object-fit:cover;
  object-position:var(--pos,center)}
.plate>img,.plate>video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;z-index:0}
/* Two scrims, not one. A bottom-only gradient assumes a dark photograph; the
   moment the image is pale the display type lands on white and disappears.
   The copy column gets its own field from the left, the bottom gradient stays
   for the lede.

   Measured over atelier.jpg (a deliberately hard case — pale cloth filling the
   frame): bottom gradient alone gives 1.00:1 worst / 1.82:1 median for muted
   ink. Two scrims give 1.16:1 worst / 4.07:1 median. Better, and still a fail.

   So the rule this file enforces is not a stronger veil — it is that PLATES
   CARRY TYPE ONLY OVER IMAGES WHOSE COPY REGION IS ALREADY DARK. A pale
   photograph runs full-bleed with no type on it, and the headline sits on the
   room, where ink measures 15.5:1 and muted ink 6.8:1. */
.plate::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(to top,rgba(12,13,15,.88) 0%,
      rgba(12,13,15,.34) 34%,rgba(12,13,15,0) 66%),
    linear-gradient(to right,rgba(12,13,15,.84) 0%,
      rgba(12,13,15,.46) 40%,rgba(12,13,15,0) 72%)}
/* narrow screens have no side column to hide in, so the veil goes flat */
@media(max-width:760px){
  .plate::after{background:linear-gradient(to top,rgba(12,13,15,.9) 0%,
    rgba(12,13,15,.66) 46%,rgba(12,13,15,.5) 100%)}
}
.plate-copy{position:relative;z-index:2;padding:var(--gut);display:grid;gap:var(--s3);
  justify-items:start;width:100%;max-width:var(--max);margin-inline:auto}

/* ---------- split ---------- */
.split{display:grid;gap:var(--s5);grid-template-columns:1fr}
@media(min-width:900px){
  .split{grid-template-columns:1fr 1fr;align-items:center;
    gap:var(--sz)}
  .split--flip>*:first-child{order:2}
}

/* ---------- footer ---------- */
.foot{background:var(--deep);padding:var(--sz) 0 var(--s5);
  border-top:1px solid var(--hair)}
/* Four stacked columns and a 200px monogram came to 956px on a phone — taller
   than the bespoke page's own content, and the same on every page of the site.
   The three link lists sit two-up below 860px, which halves it and still leaves
   every link a comfortable tap target. */
.foot-grid{display:grid;gap:var(--s5);grid-template-columns:1fr}
/* Four stacked columns and a 200px monogram came to 956px on a phone — taller
   than the bespoke page's own content, and the same on every page of the site.

   Only the last two lists pair up. Explore and Visit are short lines that sit
   happily in half of a 340px column; The house is not, because
   prashanth@iamratan.co.in is twenty-four characters and would wrap into a mess
   beside anything. So the brand block and the contact block keep the full
   width, and the two that can share, share. */
@media(min-width:860px){.foot-grid{grid-template-columns:1.5fr 1fr 1fr 1fr}}
.mark--monogram{width:min(200px,56vw);aspect-ratio:1430/620;display:block;
  background:currentColor;margin-bottom:var(--s4);
  -webkit-mask:url('mark-monogram.png') no-repeat center/contain;
  mask:url('mark-monogram.png') no-repeat center/contain}

/* Sign in sits apart from the four navigation words: it is an action, not a
   place on the site, and lining it up with Home and Shop invites a visitor to
   read it as a fifth section. Set in the mono like the rest of the bar so it
   stays quiet until wanted. */
/* The right-hand group: the cart and the two account actions, together at the
   end of the bar. They are actions, not places on the site, which is why they
   sit apart from the four navigation words rather than among them. The hairline
   is the divide between "where you can go" and "what you can do". */
.top-end{display:flex;align-items:center;gap:var(--s3);justify-self:end}
.top-end .bagbtn{margin:0}
.nav-acc{padding-left:var(--s3);border-left:1px solid var(--hair);
  color:var(--muted);white-space:nowrap}
.nav-reg{color:var(--muted);white-space:nowrap}
.nav-acc:hover,.nav-reg:hover{color:var(--ink)}
@media(max-width:1024px){
  /* On a phone the bar has room for the mark, the cart and the menu button and
     nothing else, so the two account actions ride into the drawer instead.
     nav.js moves the actual elements rather than copying them, so there is
     never a second Sign in hidden off screen for a screen reader to find. */
  .top-end{gap:var(--s2)}

  /* In the panel it stops being a link among links and becomes the action it
     is: a visitor who wants an account should not have to notice a word set in
     the same weight as Home. Drawn, not merely listed. */
  [data-nav] .nav .nav-acc{margin:var(--s4) 0 0;padding:var(--s3) var(--s4);
    border:1px solid var(--ink);border-left:1px solid var(--ink);
    color:var(--ink);text-align:center;font-family:var(--mono);
    font-size:.6875rem;letter-spacing:.18em;text-transform:uppercase;
    min-height:2.75rem;display:flex;align-items:center;justify-content:center}
  [data-nav] .nav .nav-acc:hover{background:var(--ink);color:var(--room)}

  /* Register sits under it, drawn but not filled: two identical buttons make a
     visitor choose before they know the difference, and the one most people
     want is the one they already have. */
  [data-nav] .nav .nav-reg{margin:var(--s2) 0 0;padding:var(--s3) var(--s4);
    border:1px solid var(--hair);color:var(--muted);text-align:center;
    font-family:var(--mono);font-size:.6875rem;letter-spacing:.18em;
    text-transform:uppercase;min-height:2.75rem;display:flex;
    align-items:center;justify-content:center}
  [data-nav] .nav .nav-reg:hover{border-color:var(--ink);color:var(--ink)}

  /* the house's details, at the foot of the panel */
  .nav-tail{margin-top:auto;padding-top:var(--s5);display:grid;gap:var(--s2);
    border-top:1px solid var(--hair)}
  .nav-tail a{font-size:.9375rem;color:var(--muted);min-height:0;
    padding:0;border:0}
  .nav-tail a:hover{color:var(--ink)}
  .nav-ethos{margin:var(--s2) 0 0;font-family:var(--mono);font-size:.5625rem;
    letter-spacing:.2em;text-transform:uppercase;color:var(--muted)}
  /* the panel is a column so the tail can sit at its foot */
  [data-nav] .nav{display:flex;flex-direction:column}
}
@media(min-width:1025px){.nav-tail{display:none}}

/* ---------- motion for a story page ----------
   The About page was one weight of movement: everything faded up by 14px and
   that was the whole vocabulary, so a page carrying a twenty-year story read
   as flat as a price list.

   Three additions, all slow. This house does not bounce. Nothing here moves
   more than it must, and every one of them is a still frame under
   prefers-reduced-motion rather than a faster version of itself. */

/* A photograph settles rather than appears: it comes in fractionally large and
   eases back to true, which reads as a camera coming to rest. 1.06, over 1.6s,
   is at the edge of noticing, which is the point. */
.settle img{transition:transform 1.6s var(--settle),opacity .9s var(--settle)}
[data-reveal] .settle img{transform:scale(1.06);opacity:0}
[data-reveal] .settle.in img{transform:none;opacity:1}

/* Type that arrives a line at a time, so a claim lands as two beats rather
   than one block. The mask is a clip, not an opacity fade: the line is either
   read or it is not there, which is how a printed page behaves. */
.lines>span{display:block;overflow:hidden}
.lines>span>i{display:block;font-style:inherit;transition:transform .9s var(--swing)}
[data-reveal] .lines>span>i{transform:translateY(105%)}
[data-reveal] .lines.in>span>i{transform:none}
.lines.in>span:nth-child(2)>i{transition-delay:.14s}
.lines.in>span:nth-child(3)>i{transition-delay:.28s}

/* A rule that draws itself under a word, left to right, once its column is
   read. Used on the ethos, where three words needed to feel counted out. */
.draw{height:1px;background:var(--ink);transform-origin:left;
  transition:transform .7s var(--swing)}
[data-reveal] .draw{transform:scaleX(0)}
[data-reveal] .draw.in,[data-reveal] .stag.in .draw{transform:scaleX(1)}
.stag.in>*:nth-child(1) .draw{transition-delay:.05s}
.stag.in>*:nth-child(2) .draw{transition-delay:.25s}
.stag.in>*:nth-child(3) .draw{transition-delay:.45s}

@media(prefers-reduced-motion:reduce){
  .settle>img,.settle.in>img{transform:none;opacity:1;transition:none}
  .lines>span>i,.lines.in>span>i{transform:none;transition:none}
  .draw,.draw.in{transform:scaleX(1);transition:none}
}

/* ---------- waiting ----------
   The house's own button, turning. Every shirt carries I AM RATAN engraved
   around the rim, so the one thing a customer is asked to look at while the
   site works is the detail the house is known for.

   A photograph rather than a drawn ring: a drawn spinner is the same spinner
   every site has. It turns slowly, 2.4s, because a button being examined is
   not a progress bar being raced.

   Reduced motion gets a still button and a fading opacity instead: the wait is
   still signalled, nothing rotates. */
.wait{display:inline-flex;align-items:center;gap:var(--s2);vertical-align:middle}
.wait::before{content:'';width:1.125em;height:1.125em;flex:0 0 auto;
  background:url('loader-button-128.png') center/contain no-repeat;
  animation:iarturn 2.4s linear infinite}
.wait--lg::before{width:2.75rem;height:2.75rem}
@keyframes iarturn{to{transform:rotate(360deg)}}

/* a full-panel wait, for a page that has nothing to show yet */
.waitbox{display:grid;justify-items:center;gap:var(--s3);padding:var(--sz) 0;
  color:var(--muted);text-align:center}
.waitbox::before{content:'';width:3.25rem;height:3.25rem;
  background:url('loader-button-128.png') center/contain no-repeat;
  animation:iarturn 2.4s linear infinite}

@media(prefers-reduced-motion:reduce){
  .wait::before,.waitbox::before{animation:iarpulse 1.6s ease-in-out infinite}
}
@keyframes iarpulse{0%,100%{opacity:1}50%{opacity:.45}}

/* ---------- the journal, one essay ----------
   These are essays, not product pages, so the whole layout serves one job:
   uninterrupted reading. A single column, a measure that stays near 62
   characters, and nothing in the margins to look at instead.

   The client's writing has a deliberate rhythm: many one-sentence paragraphs,
   used as beats. That is why the paragraph spacing is generous and the
   line-height is tall. Cramming those lines together would flatten the voice
   the writing is built on. */
.essay-hero{margin:0;position:relative;aspect-ratio:16/9;overflow:hidden;
  background:var(--under)}
.essay-hero img{width:100%;height:100%;object-fit:cover;object-position:var(--pos,center);
  display:block}
@media(max-width:759px){.essay-hero{aspect-ratio:4/3}}

.essay-head{max-width:38rem;margin-inline:auto;padding-top:var(--sy);
  text-align:center}
.essay-kick{margin:0}
.essay-name{font-weight:200;font-size:clamp(2rem,4.4vw,3.2rem);line-height:1.06;
  letter-spacing:-.03em;margin:var(--s2) 0 0;text-wrap:balance}
.essay-lede{font-weight:250;font-size:clamp(1.0625rem,1.5vw,1.25rem);line-height:1.55;
  color:var(--muted);margin:var(--s4) 0 0}

/* 36rem, not the 46 this was drawn at. Measured on the rendered page rather
   than judged by eye: 46rem at this size came to 94 characters a line, where
   60 to 75 is the readable band and anything past about 80 makes the eye lose
   its place on the return sweep. 36rem lands near 66. */
.essay-body{max-width:36rem;margin-inline:auto;padding-top:var(--sy);
  padding-bottom:var(--sz)}
.essay-body p{margin:0 0 1.15em;font-size:clamp(1.0625rem,1.15vw,1.1875rem);
  line-height:1.75;max-width:none}
.essay-body p:last-child{margin-bottom:0}
/* a beat between movements, not a decorative flourish */
.essay-body hr{border:0;height:1px;background:var(--hair);
  margin:var(--s6) auto;width:min(6rem,30%)}
/* One line lifted out of the argument, in the house's own voice. Set as a
   quotation rather than a heading, because that is what it is. */
.essay-body blockquote{margin:var(--s6) 0;padding:0 0 0 var(--s4);
  border-left:1px solid var(--ink);font-weight:250;
  font-size:clamp(1.25rem,2.1vw,1.6rem);line-height:1.35;letter-spacing:-.02em}
.essay-body blockquote p{font-size:inherit;line-height:inherit;margin:0}

/* what to read next, so an essay is never a dead end */
.essay-next{border-top:1px solid var(--hair);padding:var(--sy) 0 var(--sz)}
/* Held to the same measure as the essay above it. Left full width, two cards
   came to 581px each against a 576px reading column, so the footnote outweighed
   the piece it follows. */
.essay-next .wrap{display:grid;gap:var(--s4) var(--s3);
  grid-template-columns:1fr 1fr;max-width:36rem}
.enx{display:block;text-decoration:none;color:inherit}
/* 4/5, matching every other journal card on the site and, more to the point,
   the shape the photographs actually are. At 3/2 the cover crop took a wide
   strip out of a portrait frame and cut the rider's head off: a composed
   portrait rendered as a headless torso. The card follows the picture. */
.enx-shot{display:block;position:relative;aspect-ratio:4/5;overflow:hidden;
  background:var(--under);margin-bottom:var(--s3)}
.enx-shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .6s var(--settle)}
.enx:hover .enx-shot img,.enx:focus-visible .enx-shot img{transform:scale(1.03)}
.enx-name{font-weight:250;font-size:clamp(1.125rem,1.6vw,1.35rem);line-height:1.2;
  letter-spacing:-.02em;margin:var(--s1) 0 0}
@media(prefers-reduced-motion:reduce){.enx:hover .enx-shot img{transform:none}}

/* ---------- the footer on a phone ----------
   All four blocks share the two columns now. The brand and contact blocks used
   to span the full width on the stated grounds that the email was too long to
   sit beside anything — measured, prashanth@iamratan.co.in is 173px and half a
   column is 199px. It fits, and holding two blocks at full width for a reason
   that was not true cost about 290px of empty right-hand side.

   This rule sits AFTER the base .mark--monogram on purpose. It was written
   before it, and since a media query adds no specificity the base width simply
   won on source order — the monogram asked for 150px and rendered at 200px on
   every phone. */
@media(max-width:859px){
  .foot-grid{grid-template-columns:1fr 1fr;gap:var(--sy) var(--s4)}
  /* a signature, not a billboard */
  .mark--monogram{width:min(120px,32vw);margin-bottom:var(--s3)}
  /* The address is never broken across lines. overflow-wrap:anywhere let it
     split mid-domain into "prashanth@iamratan.c / o.in", which reads as a
     typo rather than as a wrap.

     Half a column only fits the 173px address from about 440px up: at 375 it
     is 158px and at 320 it is 130px. The claim above that it fits was measured
     at a single width and generalised, which is exactly the trap. So below
     460px the brand and contact blocks take the full width and only the two
     short lists pair up. */
  .foot a[href^="mailto"]{white-space:nowrap}
}
@media(max-width:459px){
  /* :has() rather than nth-child so this keeps working if a block is ever
     added or reordered: the rule follows the address, not a position. Both
     blocks span, not just the contact one — spanning only the second would
     leave a hole beside the brand block, since a full-width item forces a new
     row and cannot back-fill the column above it. */
  .foot-grid>div:first-child,
  .foot-grid>div:has(a[href^="mailto"]){grid-column:1/-1}
}
.foot ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--s1)}
.foot a:hover{text-decoration:underline;text-underline-offset:5px}

/* REACHABLE ON A THUMB
   Every link down here was a 17px line of type, and the legal row was 13px.
   A target has to be 24px to be hit reliably, and these are the links a phone
   user reaches for: the phone number, the email, the shop.

   padding-block on an INLINE box grows what the finger can hit without moving
   the line it sits on, so the footer still looks exactly as it did. The list
   gap is --s1, which is why --s0 is the most each list link can take: any more
   and two stacked targets would start to overlap and the wrong one would win.
   The legal row is a single line with nothing above or below it to collide
   with, so it can afford the full step. */
.foot li a{padding-block:var(--s0)}
.colophon a{padding-block:var(--s1)}
.colophon{margin-top:var(--s6);padding-top:var(--s4);border-top:1px solid var(--hair);
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);justify-content:space-between;
  color:var(--muted)}

@media(prefers-reduced-motion:reduce){
  .snap,.snap.in,.rise,.rise.in{transform:none;opacity:1;transition:none}
  a.shot:hover img{transform:none}
}
