/* ============================================================================
   RANGHAAT HANDLOOMS — Hollowmere Mall, Parkside, Kolkata
   Designed and built by Silicon Insights.

   THE DECISION THAT DRIVES EVERYTHING HERE.
   The first build put a saturated indigo ground and a madder band behind
   photographs of sarees that are already loud. The site competed with the
   goods and lost. So this one has NO chromatic accent at all. Ground is the
   warm black of their own block-print ink; text is the undyed cotton they
   photograph everything on; the primary button is that same cloth. Every
   colour a reader sees comes out of a photograph.

   PALETTE, from their own material.
     --ink       #14110E  warm near-black. Printing ink, not a blue-black
     --ink-2     #1C1815  one step up, for the rare raised surface
     --ink-3     #262119  image mattes and menu grounds
     --cloth     #EFE7DA  undyed cotton, the studio cloth they shoot on
     --cloth-2   #C6BAA8  the same, dimmed, for secondary text
     --cloth-3   #8A8074  quiet metadata only
   Kept for one use each, never as a surface:
     --indigo    #1B3A66  focus ring fallback, and the shader's key light
     --madder    #8E1634  reserved. Do not spend it casually.

   CONTRAST, computed:
     cloth on ink ............. 14.28:1  AA body
     cloth-2 on ink ...........  9.28:1  AA body
     cloth-3 on ink ...........  4.62:1  AA body, metadata only
     ink on cloth ............. 14.28:1  AA body  (the primary button)
   Nothing dimmer than --cloth-3 carries text anywhere.

   TYPE. Silicon Insights sets a Didone at large scale with negative tracking
   over a quiet geometric sans. Same language here, different faces, because a
   client site using the studio's own fonts looks like the studio.
     display  Prata  (Cyreal, OFL verified live 4 Sep 2026)
     body     Jost   (Owen Earl, OFL verified live 4 Sep 2026)

   RHYTHM. No alternating colour bands. One continuous ink ground, with the
   rhythm coming from photographs and from space. The colour bands are what
   broke the reading in the first build.
   ========================================================================= */

:root {
  --ink:      #14110E;
  --ink-2:    #1C1815;
  --ink-3:    #262119;
  --cloth:    #EFE7DA;
  --cloth-2:  #C6BAA8;
  --cloth-3:  #8A8074;
  --indigo:   #1B3A66;
  --madder:   #8E1634;

  --bg:   var(--ink);
  --fg:   var(--cloth);
  --fg-2: var(--cloth-2);
  --fg-3: var(--cloth-3);
  --line:   rgba(239, 231, 218, .13);
  --line-2: rgba(239, 231, 218, .26);
  --focus:  var(--cloth);

  --font-display: Prata, "Bodoni 72", Didot, "Times New Roman", serif;
  --font-body: Jost, "Helvetica Neue", system-ui, Arial, sans-serif;

  /* A wide scale. The first build's steps sat too close and read flat. */
  --fs-max: clamp(2.7rem, 1.1rem + 6.4vw, 5.7rem);
  --fs-900: clamp(2.3rem, 1.2rem + 4.4vw, 4.2rem);
  --fs-800: clamp(1.72rem, 1.2rem + 2.1vw, 2.6rem);
  --fs-700: clamp(1.3rem, 1.12rem + .8vw, 1.7rem);
  --fs-600: clamp(1.08rem, 1.0rem + .4vw, 1.24rem);
  --fs-400: 1rem;
  --fs-300: .875rem;
  --fs-200: .75rem;

  --gap: clamp(5rem, 3rem + 8vw, 11rem);
  --pad: clamp(1.15rem, 5vw, 3.4rem);
  --measure: 58ch;

  --r: 0px;            /* one radius system: square. Stated and followed. */
  --r-pill: 999px;     /* the single pill shape, on buttons only */
  --ease: cubic-bezier(.22, 1, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 5rem; }

body {
  margin: 0; min-height: 100svh;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--fg);
  font-family: var(--font-body); font-size: var(--fs-400);
  font-weight: 300; line-height: 1.68; letter-spacing: .006em;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-display); font-weight: 400;
  line-height: 1.04; letter-spacing: -0.021em;
  margin: 0 0 .44em; text-wrap: balance;
}
h1 { font-size: var(--fs-900); }
h2 { font-size: var(--fs-800); }
h3 { font-size: var(--fs-700); letter-spacing: -0.014em; }

p, li { max-width: var(--measure); }
p { margin: 0 0 1.2em; }
a { color: inherit; }
img { max-width: 100%; height: auto; display: block; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

@font-face {
  font-family: Prata; src: url("../fonts/prata-latin.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face {
  font-family: Jost; src: url("../fonts/jost-latin.woff2") format("woff2");
  font-weight: 300 600; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

/* ---------- the surface ----------
   The gradient IS the still fallback: no JS, reduced motion, no WebGL2,
   narrow, two cores or Save-Data, and this carries the page alone. */
.stage {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    linear-gradient(163deg, #1A1611 0%, #14110E 46%, #100D0B 100%),
    linear-gradient(78deg, #171310 0%, #14110E 60%);
}
.stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.skip, .top, main, .foot, .callbar, .cookie { position: relative; z-index: 1; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--cloth); color: var(--ink); padding: .8rem 1.2rem;
}
.skip:focus { left: .6rem; top: .6rem; }

/* ---------- top bar ---------- */
.top {
  position: sticky; top: 0; z-index: 40;
  background: rgba(20, 17, 14, .78);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--line);
}
.top__in {
  max-width: 84rem; margin: 0 auto; padding: .7rem var(--pad);
  display: flex; align-items: center; gap: 1.2rem; min-height: 64px;
}
.brand {
  display: inline-flex; align-items: center; gap: .62rem;
  text-decoration: none; color: var(--cloth); margin-right: auto;
  font-family: var(--font-display); font-size: 1.32rem; letter-spacing: .012em;
}
.brand svg { width: 27px; height: 27px; flex: none; }

.nav { display: flex; align-items: center; gap: clamp(.5rem, 1.5vw, 1.4rem); }
.nav > * { position: relative; }
.nav a, .nav .drop__btn {
  font-family: var(--font-body); font-size: var(--fs-200);
  letter-spacing: .15em; text-transform: uppercase; font-weight: 400;
  color: var(--fg-2); text-decoration: none;
  background: none; border: 0; cursor: pointer;
  padding: .8rem .2rem; display: inline-flex; align-items: center; gap: .34rem;
  transition: color .2s var(--ease);
}
@media (hover: hover) { .nav a:hover, .nav .drop__btn:hover { color: var(--cloth); } }
.nav a[aria-current="page"] { color: var(--cloth); }
.drop__btn svg { width: 9px; height: 9px; opacity: .7; }

/* A real dropdown. In the first build the reader had to know to click a
   heading inside a card, and most never would. */
.drop__menu {
  position: absolute; top: 100%; left: -1rem; min-width: 17rem;
  background: var(--ink-2); border: 1px solid var(--line);
  padding: .45rem; margin: 0; list-style: none;
  box-shadow: 0 24px 48px rgba(0,0,0,.5);
}
.drop__menu[hidden] { display: none; }
.drop__menu li { max-width: none; }
.drop__menu a {
  display: block; padding: .62rem .8rem; letter-spacing: .04em;
  text-transform: none; font-size: var(--fs-300); color: var(--fg-2);
}
@media (hover: hover) { .drop__menu a:hover { background: var(--ink-3); color: var(--cloth); } }

.navtoggle {
  display: none; background: none; border: 1px solid var(--line-2);
  color: var(--cloth); min-width: 46px; min-height: 46px; cursor: pointer;
  font-family: var(--font-body); font-size: var(--fs-200);
  letter-spacing: .12em; text-transform: uppercase; padding: 0 .85rem;
}
.navtoggle:active { transform: scale(.97); }

@media (max-width: 900px) {
  .navtoggle { display: inline-block; }
  .nav {
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--ink-2); border-bottom: 1px solid var(--line);
    flex-direction: column; align-items: stretch; gap: 0; padding: .3rem 0;
    max-height: 74svh; overflow-y: auto;
  }
  .nav[hidden] { display: none; }
  .nav > * { width: 100%; }
  .nav a, .nav .drop__btn {
    padding: .95rem var(--pad); width: 100%;
    border-bottom: 1px solid var(--line); justify-content: space-between;
  }
  .drop__menu {
    position: static; border: 0; box-shadow: none; padding: 0;
    background: var(--ink-3); min-width: 0;
  }
  .drop__menu a { padding-left: calc(var(--pad) + 1rem); }
}

/* ---------- layout ---------- */
.wrap { max-width: 84rem; margin: 0 auto; padding: 0 var(--pad); }
.narrow { max-width: 46rem; }
section { padding-block: var(--gap); }
section + section { padding-top: 0; }

/* A full-bleed photograph needs air after it. Without this the next section's
   own image starts on the bleed's bottom edge and the two read as one broken
   picture. */
.bleed + section { padding-top: var(--gap); }
.bleed { margin-block: 0; }

.eyebrow {
  font-size: var(--fs-200); letter-spacing: .2em; text-transform: uppercase;
  color: var(--fg-3); margin: 0 0 1.4rem; font-weight: 400;
  display: flex; align-items: center; gap: .8rem;
}
.eyebrow::before {
  content: ""; width: 2.2rem; height: 1px; flex: none;
  background: currentColor; opacity: .6;
}
.lede {
  font-family: var(--font-display); font-size: var(--fs-700);
  line-height: 1.36; letter-spacing: -0.012em; color: var(--fg); max-width: 34ch;
}
.muted { color: var(--fg-2); }
.small { font-size: var(--fs-300); }

/* ---------- hero ---------- */
.hero { padding-block: clamp(3rem, 1.6rem + 7vw, 7rem); }
.hero h1 {
  font-size: var(--fs-max); letter-spacing: -0.03em; line-height: .97;
  max-width: 15ch; margin-bottom: .42em;
}
.hero__sub { max-width: 40ch; }

/* ---------- buttons ----------
   One primary: cloth on ink, the only filled thing on the site. No gold and
   no chromatic accent anywhere. Secondary is a hairline. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 50px; padding: .8rem 1.9rem;
  font-family: var(--font-body); font-size: var(--fs-300); font-weight: 400;
  letter-spacing: .09em; text-transform: uppercase; text-decoration: none;
  border: 1px solid transparent; border-radius: var(--r-pill); cursor: pointer;
  transition: background-color .22s var(--ease), color .22s var(--ease),
              border-color .22s var(--ease), transform .16s var(--ease);
}
.btn:active { transform: scale(.985); }
.btn--fill { background: var(--cloth); color: var(--ink); }
.btn--line { border-color: var(--line-2); color: var(--fg); }
@media (hover: hover) {
  .btn--fill:hover { background: #FFFAF2; }
  .btn--line:hover { border-color: var(--cloth); }
}
.btn-row { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 2.2rem; }

.textlink {
  display: inline-block; color: var(--fg); text-decoration: none;
  border-bottom: 1px solid var(--line-2); padding-bottom: 3px;
  transition: border-color .2s var(--ease);
}
@media (hover: hover) { .textlink:hover { border-bottom-color: var(--cloth); } }

/* ---------- editorial pairs ---------- */
.duo { display: grid; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
@media (min-width: 900px) {
  .duo { grid-template-columns: 1fr 1fr; }
  .duo--text-first { grid-template-columns: 1fr 1.15fr; }
  .duo--image-first { grid-template-columns: 1.15fr 1fr; }
}

figure { margin: 0; }
figure img { border-radius: var(--r); background: var(--ink-3); }
figcaption { color: var(--fg-3); font-size: var(--fs-300); margin-top: .85rem; }

/* a full-bleed photograph, the page's punctuation instead of a colour band */
/* THE FULL-BLEED BAND IS GONE, on purpose.
   These photographs are between 330 and 550 px on their long edge. Stretching
   one edge to edge on a desktop upscaled it about four times and cropped a
   portrait source into a letterbox, which is exactly what read as broken. A
   picture is never shown wider than this source can carry.

   Instead: a contained row of three, at a shape close to what was shot. */
.strip { }
.strip ul {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(.8rem, 1.6vw, 1.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 700px) { .strip ul { grid-template-columns: repeat(3, 1fr); } }
.strip li { max-width: none; }
.strip img {
  width: 100%; aspect-ratio: Reviewed on Google; object-fit: cover;
  background: var(--ink-3);
}
.strip figcaption { margin-top: 1.1rem; }

/* ---------- the collection, as a list of rows, not a card grid ----------
   In the first build only the heading inside each card was a link. Here the
   whole row is one link. */
.index { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.index li { max-width: none; border-bottom: 1px solid var(--line); }
.index a {
  display: grid; grid-template-columns: 1fr auto; align-items: baseline;
  gap: .6rem 2rem; padding: clamp(1.5rem, 3vw, 2.4rem) 0;
  text-decoration: none; color: var(--fg);
  transition: padding-left .32s var(--ease);
}
.index h3 { margin: 0 0 .35rem; }
.index p { margin: 0; color: var(--fg-2); font-size: var(--fs-300); max-width: 54ch; }
.index .go {
  font-size: var(--fs-200); letter-spacing: .16em; text-transform: uppercase;
  color: var(--fg-3); white-space: nowrap; justify-self: end;
  transition: color .2s var(--ease), transform .32s var(--ease);
}
@media (hover: hover) {
  .index a:hover { padding-left: 1.1rem; }
  .index a:hover .go { color: var(--cloth); transform: translateX(5px); }
}

/* ---------- pieces ---------- */
.grid {
  list-style: none; margin: 3rem 0 0; padding: 0;
  display: grid; gap: clamp(2.2rem, 4vw, 3.6rem) clamp(1.2rem, 2.4vw, 2.2rem);
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
}
.grid > li { max-width: none; }
.piece { display: flex; flex-direction: column; height: 100%; }
.piece__shot {
  width: 100%; aspect-ratio: Reviewed on Google; object-fit: cover;
  background: var(--ink-3); border-radius: var(--r);
}
.piece__shot--wide { aspect-ratio: 3 / 2; }
.piece__name {
  font-family: var(--font-display); font-size: var(--fs-600); font-weight: 400;
  letter-spacing: -0.01em; margin: 1.05rem 0 .25rem;
}
.piece__note { color: var(--fg-2); font-size: var(--fs-300); margin: 0 0 .8rem; }
.piece__ask {
  margin-top: auto; align-self: flex-start; text-decoration: none;
  font-size: var(--fs-300); color: var(--fg-3); min-height: 26px;
  border-bottom: 1px solid var(--line); padding-bottom: 3px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
@media (hover: hover) { .piece__ask:hover { color: var(--cloth); border-bottom-color: var(--line-2); } }

/* ---------- questions ---------- */
/* The closing block after a grid of pieces needs real separation, or its
   heading lands on top of the last card's caption. */
.grid + section, .tailblock { padding-top: var(--gap); }
.tailblock { border-top: 1px solid var(--line); margin-top: var(--gap); }

.qa { border-top: 1px solid var(--line); padding-top: 2rem; margin-top: 2rem; }
.qa h2 { font-size: var(--fs-700); margin-bottom: .6rem; }
.qa p:last-child { margin-bottom: 0; }

/* ---------- breadcrumbs ---------- */
.crumbs { padding-top: 1.6rem; font-size: var(--fs-200); color: var(--fg-3); }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; }
.crumbs li { max-width: none; }
.crumbs li::after { content: "/"; margin-left: .5rem; opacity: .5; }
.crumbs li:last-child::after { content: ""; }
.crumbs a { color: var(--fg-3); text-decoration: none; }
@media (hover: hover) { .crumbs a:hover { color: var(--cloth); } }

/* ---------- getting there ----------
   No embedded map. A Google Maps iframe sets cookies, which would make the
   site's own "we set no cookies" line untrue and would require a real consent
   gate.The concept site embeds no map. So neither: a
   designed block, and a button that opens Google Maps properly. */
.where {
  border: 1px solid var(--line); padding: clamp(1.6rem, 4vw, 2.8rem);
  background: rgba(28, 24, 21, .55);
}
.where dl { margin: 0; display: grid; gap: 1.5rem 2.5rem; }
@media (min-width: 620px) { .where dl { grid-template-columns: auto 1fr; } }
.where dt {
  font-size: var(--fs-200); letter-spacing: .18em; text-transform: uppercase;
  color: var(--fg-3); margin: 0; padding-top: .28rem;
}
.where dd { margin: 0; color: var(--fg); font-size: var(--fs-400); line-height: 1.75; max-width: 46ch; }
.where dd .small { color: var(--fg-2); }

/* ---------- the map ----------
   It sat behind a button until 5 Sep 2026, so the site could claim it set no
   cookies. Bose asked for it to simply load, so it does, and the cookie notice
   and privacy page were changed to say plainly that Google sets its own. The
   claim follows the site rather than the site following the claim. */
.mapbox { margin-top: clamp(2rem, 4vw, 3rem); }
.mapbox__frame {
  display: block; width: 100%; aspect-ratio: 16 / 10;
  border: 1px solid var(--line); background: var(--ink-3);
}
.mapbox__note { color: var(--fg-3); font-size: var(--fs-200); margin-top: .9rem; }

/* ---------- footer ---------- */
.foot {
  margin-top: var(--gap); border-top: 1px solid var(--line);
  padding-block: clamp(3rem, 2rem + 4vw, 5rem);
  padding-bottom: calc(clamp(3rem, 2rem + 4vw, 5rem) + var(--callbar-pad, 0px));
  background: var(--ink);
}
.foot__grid { display: grid; gap: 2.4rem; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.foot__h {
  font-family: var(--font-body); font-size: var(--fs-200); font-weight: 400;
  letter-spacing: .2em; text-transform: uppercase; color: var(--fg-3);
  margin: 0 0 1.1rem; line-height: 1.4;
}
.foot ul { list-style: none; margin: 0; padding: 0; }
.foot li { margin-bottom: .55rem; max-width: none; }
.foot a { color: var(--fg-2); text-decoration: none; font-size: var(--fs-300); }
@media (hover: hover) { .foot a:hover { color: var(--cloth); } }
.foot address { font-style: normal; color: var(--fg-2); font-size: var(--fs-300); line-height: 1.8; }
.foot__base {
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: .7rem 1.8rem;
  font-size: var(--fs-200); color: var(--fg-3);
}
.foot__credit a { color: inherit; text-decoration: underline; text-underline-offset: .22em; }

/* ---------- sticky call bar ---------- */
.callbar { display: none; }
@media (max-width: 760px) {
  .callbar {
    display: grid; grid-template-columns: 1fr 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    background: var(--ink-2); border-top: 1px solid var(--line-2);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .callbar a {
    display: flex; align-items: center; justify-content: center;
    min-height: 54px; text-decoration: none; color: var(--cloth);
    font-size: var(--fs-300); letter-spacing: .06em;
  }
  .callbar a + a { border-left: 1px solid var(--line); }
  .callbar a:active { background: var(--ink-3); }
  body { --callbar-pad: 56px; }
}

/* ---------- the cookie line ----------
   Not a consent banner, because there is nothing to consent to. One honest
   sentence that dismisses and stays dismissed. */
.cookie {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  background: var(--ink-2); border-top: 1px solid var(--line);
  padding: .85rem var(--pad);
  display: flex; flex-wrap: wrap; align-items: center; gap: .8rem 1.4rem;
  font-size: var(--fs-300); color: var(--fg-2);
}
.cookie[hidden] { display: none; }
.cookie p { margin: 0; max-width: 72ch; }
.cookie button {
  margin-left: auto; background: none; border: 1px solid var(--line-2);
  color: var(--cloth); font-family: var(--font-body); font-size: var(--fs-300);
  padding: .5rem 1.1rem; min-height: 44px; cursor: pointer; border-radius: var(--r-pill);
}
@media (hover: hover) { .cookie button:hover { border-color: var(--cloth); } }
@media (max-width: 760px) { .cookie { bottom: 56px; } }
/* While the notice is up it must not sit on top of anything. JS adds this
   class, so the page reserves the room rather than covering its own buttons. */
body.has-notice { padding-bottom: 4.5rem; }
@media (max-width: 760px) { body.has-notice { padding-bottom: 8.5rem; } }

/* ---------- reveals ----------
   Added by JS only, so nothing is ever born hidden. Transform and visibility
   only; text opacity is never animated. */
.js .rv { visibility: hidden; transform: translateY(16px); }
.js .rv-in { visibility: visible; transform: none; transition: transform .75s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .js .rv, .js .rv-in { visibility: visible; transform: none; transition: none; }
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  html { scroll-behavior: auto !important; }
}

@media print {
  .stage, .top, .callbar, .cookie { display: none !important; }
  .rv, .rv-in { visibility: visible !important; transform: none !important; }
  body { background: #fff; color: #111; }
}

.vh { position: absolute !important; width: 1px; height: 1px; overflow: hidden;
      clip: rect(0 0 0 0); white-space: nowrap; }
.mt0 { margin-top: 0; }
