/* ============================================================================
   RADIO MALLU — site stylesheet
   ----------------------------------------------------------------------------
   Subject. A living archive of Malayalam music, memory and culture: 36
   collections, 585 entries, in Malayalam and English. The visitor is reading
   and browsing, not buying, so the design's job is to make a large archive
   feel navigable and worth staying in.

   The one decision everything else serves. A MALAYALAM ARCHIVE IS SET IN
   MALAYALAM TYPE, and specifically in type drawn in Kerala. The export set the
   entire site in Arial and Georgia with "Noto Sans Malayalam" listed as a
   fallback, which is the system default wearing the clothes of a decision:
   the most beautiful thing this site owns, the script itself, was being
   rendered in whatever the browser had lying around.

   Display is GAYATHRI, by the Rachana Institute of Typography in Kozhikode.
   Text is MANJARI, by Santhosh Thottingal. Both are SIL OFL, both carry Latin
   as well as Malayalam, so the whole site including its English runs on two
   families where it previously used four. A headline in Gayathri is
   unmistakably this site and could not be lifted onto anyone else's.

   Imagery is thin and the design must not pretend otherwise. The hero photo
   is 728x410 and was being stretched across a 1440px viewport at 2x, which is
   why it read as a blur; the median file in media/ is 800px wide. So the hero
   is TYPOGRAPHIC. The house guide is explicit that a typographic hero is the
   strongest move when imagery is thin and a lie when it is not, and here it is
   the truth: the script does the work a photograph cannot do at this size.
   Nothing is ever upscaled past about 1.3x anywhere on the site.

   Palette. Warm paper and a warm near-black, both carried over from the export
   because they were right. The red is unchanged in hue and changed completely
   in use: it was decorating section numbers, where it made a filing artefact
   the loudest thing on the page. It is now spent on one thing, the act of
   listening, which is the only action this site asks anyone to take.

   Contrast measured, not assumed: ink 16.4:1, body 15.1:1, muted 5.0:1 and the
   red 4.6:1 on paper; paper 16.4:1 and muted 7.4:1 on ink.
   ========================================================================= */

:root {
  --ink:      #14130f;   /* warm near-black */
  --text:     #1e1c16;
  --muted:    #6b675c;   /* 5.0:1 on paper */
  --paper:    #f3f1e8;
  --white:    #fbfaf5;
  --mount:    #e6e3d8;   /* the ground a picture sits ON */
  --line:     rgba(20, 19, 15, 0.14);
  --rule:     #c9c5b6;
  --signal:   #c0402a;   /* 4.6:1 on paper. Listening, and nothing else. */
  --signal-hi:#e2624a;   /* 5.4:1 on ink */

  --display: "Gayathri", "Noto Sans Malayalam", Georgia, serif;
  --read:    "Manjari", "Noto Sans Malayalam", -apple-system, "Segoe UI", Arial, sans-serif;

  --shell: 1320px;
  --pad: clamp(24px, 5vw, 80px);
  --band: clamp(64px, 8vw, 128px);
  --ease: cubic-bezier(.22,.61,.36,1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; background: var(--paper); }
body {
  margin: 0; background: var(--paper); color: var(--text);
  font-family: var(--read); font-size: 17px; line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
a { color: inherit; text-decoration: none; }
button, input { font: inherit; }
button { color: inherit; }
img { display: block; max-width: 100%; }
::selection { background: var(--signal); color: var(--white); }
:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

/* ---------- masthead ---------- */
.site-shell { min-height: 100vh; padding-bottom: 82px; }
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 50; height: 78px;
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 28px; padding: 0 var(--pad);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(16px);
}
.brand { display: flex; align-items: center; gap: 13px; min-width: 0; }
.brand img { width: 42px; height: 42px; object-fit: contain; }
.brand span { display: grid; line-height: 1; }
.brand b { font-family: var(--display); font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
.brand small {
  margin-top: 7px; color: var(--muted);
  font: 500 10px/1 var(--read); letter-spacing: .2em; text-transform: uppercase;
}
.primary-nav { display: flex; justify-content: center; gap: clamp(14px, 2vw, 32px); }
/* Sentence case, not tracked capitals. Small letterspaced caps at reading size
   slow a reader down without adding any hierarchy, which is why they read as
   decoration: they are. */
.primary-nav a {
  position: relative; padding: 29px 0 26px;
  font: 500 14px/1 var(--read); letter-spacing: 0; color: var(--muted);
  text-transform: lowercase;
  transition: color 180ms var(--ease);
}
.primary-nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 20px;
  height: 1px; background: var(--ink); transition: right .28s var(--ease);
}
.primary-nav a:hover { color: var(--ink); }
.primary-nav a:hover::after, .primary-nav a.active::after { right: 0; }
.primary-nav a.active { color: var(--ink); }
.primary-nav a::first-letter { text-transform: uppercase; }
.header-actions { display: flex; align-items: center; gap: 10px; }
.listen-button, .menu-button { border: 0; background: transparent; cursor: pointer; }
.listen-button {
  display: flex; align-items: center; gap: 9px; padding: 11px 18px;
  border: 1px solid var(--ink); background: var(--ink); color: var(--paper);
  font: 500 14px/1 var(--read); min-height: 44px;
  transition: background 180ms var(--ease), color 180ms var(--ease);
}
.listen-button:hover { background: var(--signal); border-color: var(--signal); }
.listen-button i {
  width: 0; height: 0; border-top: 4px solid transparent;
  border-bottom: 4px solid transparent; border-left: 7px solid currentColor;
}
.menu-button { width: 46px; height: 46px; display: grid; place-content: center; gap: 6px; }
.menu-button span { display: block; width: 22px; height: 1px; background: var(--ink); }

/* ---------- all-sections panel ---------- */
.menu-panel {
  position: fixed; z-index: 80; top: 0; right: 0; bottom: 0;
  width: min(680px, 94vw); padding: 26px 34px 60px;
  background: var(--ink); color: var(--paper);
  transform: translateX(102%); transition: transform .45s cubic-bezier(.77,0,.18,1);
  overflow-y: auto;
}
.menu-panel.open { transform: translateX(0); }
.menu-scrim { position: fixed; z-index: 70; inset: 0; border: 0; background: rgba(15,17,14,.5); backdrop-filter: blur(3px); }
.menu-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: 22px; border-bottom: 1px solid rgba(255,255,255,.18);
  font: 500 14px/1 var(--read); color: rgba(255,255,255,.62);
}
.menu-panel-head button { border: 0; background: transparent; color: white; font-size: 32px; font-weight: 200; cursor: pointer; line-height: 1; }
.menu-search { display: block; padding: 28px 0 18px; }
.menu-search span { display: block; margin-bottom: 10px; color: rgba(255,255,255,.5); font: 500 13px/1 var(--read); }
.menu-search input {
  width: 100%; border: 0; border-bottom: 1px solid rgba(255,255,255,.36);
  padding: 5px 0 14px; outline: none; background: transparent; color: white;
  font-family: var(--display); font-size: 27px;
}
.menu-search input::placeholder { color: rgba(255,255,255,.26); }
.menu-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 30px; }
.menu-grid a {
  display: flex; gap: 14px; align-items: baseline; padding: 15px 10px 15px 0;
  border-bottom: 1px solid rgba(255,255,255,.13);
  font: 500 15px/1.3 var(--read);
  transition: color .2s var(--ease), padding-left .2s var(--ease);
}
.menu-grid a:hover, .menu-grid a.active { color: var(--signal-hi); padding-left: 7px; }
.menu-grid a span { color: rgba(255,255,255,.34); font-size: 11px; }

/* ============================================================================
   HERO — typographic. See the note at the top of this file: the source photo
   is 728x410 and this was a full-bleed cover background, so it ran at 2x and
   read as a blur, under a 76vh block that pushed every word of every page
   below the fold. Thirty-five of the thirty-seven pages had no photograph at
   all and were simply a dark void with a headline at the bottom of it.
   ========================================================================= */
.hero {
  position: relative; margin-top: 78px;
  padding: clamp(56px, 7vw, 104px) var(--pad) clamp(40px, 4.5vw, 64px);
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(28px, 4vw, 64px); align-items: end;
  background: var(--paper); color: var(--ink);
  border-bottom: 1px solid var(--line);
}
/* The home page carried its photograph as a hero background. It is not used
   as one now, for two reasons: at 728x410 it cannot fill a viewport without
   running at 2x, and the very same file is the first content block on the page
   directly underneath, so the hero was showing the reader the same picture
   twice before they had scrolled. It keeps its place in the content below,
   where it is at its own size and is doing a job. Every one of the 37 heroes
   is now the same shape. */
.hero-home { background-image: none !important; }
.hero-content { min-width: 0; }
.hero h1 {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(40px, 6.4vw, 92px); line-height: 1.04;
  letter-spacing: -.028em; text-wrap: balance;
}
.hero-category h1 { font-size: clamp(38px, 5.6vw, 78px); }
/* the site tagline, moved out of the eyebrow slot above the headline */
.hero-deck {
  margin: clamp(18px, 2vw, 28px) 0 0; max-width: 42ch;
  color: var(--muted); font-size: clamp(17px, 1.5vw, 21px); line-height: 1.5;
}
.hero-meta {
  display: flex; flex-wrap: wrap; gap: 16px; margin-top: clamp(22px, 2.4vw, 34px);
  color: var(--muted); font-size: 14px;
}
.hero-meta span + span { padding-left: 16px; border-left: 1px solid var(--rule); }
.hero-listen {
  width: 260px; flex: 0 0 auto; border: 0; padding: 0; background: transparent;
  color: var(--ink); display: flex; align-items: center; gap: 15px;
  text-align: left; cursor: pointer; align-self: end;
}
.play-disc {
  width: 62px; height: 62px; flex: 0 0 auto;
  border: 1px solid var(--ink); border-radius: 50%;
  display: grid; place-items: center;
  transition: background .25s var(--ease), color .25s var(--ease), transform .25s var(--ease);
}
.play-disc i, .player-icon i {
  width: 0; height: 0; border-top: 6px solid transparent;
  border-bottom: 6px solid transparent; border-left: 10px solid currentColor; margin-left: 3px;
}
.hero-listen:hover .play-disc { background: var(--signal); border-color: var(--signal); color: var(--white); transform: scale(1.04); }
.hero-listen b, .hero-listen small { display: block; }
.hero-listen b { font-size: 15px; font-weight: 700; }
.hero-listen small { margin-top: 5px; color: var(--muted); font-size: 13px; line-height: 1.4; }

/* ============================================================================
   CONTENT
   ========================================================================= */
.page-intro {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 20px;
  margin: 0 var(--pad); padding: 26px 0; border-bottom: 1px solid var(--line);
}
/* The section numbers were set in the red. They are a filing artefact, and in
   the accent colour they were the loudest thing on a page whose actual subject
   is the music. Muted, they still do their job of marking position. */
.page-intro span, .section-heading > span {
  color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums;
}
.page-intro p { margin: 0; max-width: 62ch; color: var(--muted); font-size: 17px; }

.content-wrap { padding: 0 var(--pad) var(--band); max-width: var(--shell); margin-inline: auto; }
.content-section { padding: var(--band) 0 0; }
.section-heading {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 20px;
  align-items: start; margin-bottom: clamp(28px, 3vw, 44px);
}
.section-heading > span { padding-top: 12px; }
/* The export emits `<div class="section-heading"><span>01</span><div></div></div>`
   wherever a section had no title, which rendered as a lone number floating
   above a picture with nothing to number. No heading, no heading row. */
.section-heading:has(> div:empty) { display: none; }
.section-heading h2 {
  max-width: 22ch; margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(28px, 3.6vw, 52px); line-height: 1.08;
  letter-spacing: -.028em; text-wrap: balance;
}

/* ---------- cards ---------- */
.card-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
}
.card-grid.single { grid-template-columns: minmax(0, 1fr); }
.archive-card { min-width: 0; background: var(--white); overflow: hidden; display: flex; flex-direction: column; }
.card-grid.single .archive-card { display: grid; grid-template-columns: minmax(260px, .85fr) minmax(300px, 1.15fr); }
/* A mount, not a letterbox. These are archive scans of varying shape and
   `contain` is the honest fit for them, but the ground behind was near-black,
   so every picture that did not happen to be 4:3 sat in a pair of black bars.
   On paper it reads as a print on a mountboard. */
.card-media { aspect-ratio: 4/3; overflow: hidden; background: var(--mount); }
/* The featured card had a 420px floor with `contain`, so a landscape
   photograph sat in the middle of a tall grey box with a band of mount above
   and below it. Sized to the picture instead. */
.card-grid.single .card-media { aspect-ratio: 3 / 2; min-height: 0; }
.card-media img {
  width: 100%; height: 100%; object-fit: contain;
  transition: transform .4s var(--ease);
}
.archive-card:hover .card-media img { transform: scale(1.02); }

/* ---- a card whose picture is a still from a video it links to ----
   Added by site.js, and only to the 83 cards that actually have one. The
   picture is the obvious thing to click and it did nothing; now it plays.
   The badge is drawn, not an emoji and not an icon font: a bordered disc and
   a CSS triangle, the same mark the site already uses for its radio player,
   so the two "press this to hear something" controls agree. */
.card-media.playable { position: relative; }
.card-play {
  position: absolute; inset: 0; width: 100%; border: 0; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--white);
  transition: background 220ms var(--ease);
}
.card-play:hover, .card-play:focus-visible { background: rgba(20, 19, 15, .34); }
.card-play-disc {
  width: 62px; height: 62px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .82);
  background: rgba(20, 19, 15, .42);
  display: grid; place-items: center;
  backdrop-filter: blur(2px);
  transition: background 220ms var(--ease), color 220ms var(--ease), transform 220ms var(--ease);
}
.card-play:hover .card-play-disc, .card-play:focus-visible .card-play-disc {
  background: var(--signal); border-color: var(--signal); transform: scale(1.06);
}
.card-play-disc i {
  width: 0; height: 0; margin-left: 4px;
  border-top: 9px solid transparent; border-bottom: 9px solid transparent;
  border-left: 15px solid currentColor;
}
/* once it is playing the box belongs to the player */
.card-media.playing { background: var(--ink); }
.card-media.playing iframe { width: 100%; height: 100%; border: 0; display: block; }
@media (max-width: 760px) {
  .card-play-disc { width: 52px; height: 52px; }
  .card-play-disc i { border-top-width: 7px; border-bottom-width: 7px; border-left-width: 12px; }
}
.card-body { padding: clamp(22px, 2.6vw, 36px); display: flex; flex-direction: column; flex: 1; }
.card-body h3 {
  margin: 0 0 14px; font-family: var(--display); font-weight: 700;
  font-size: clamp(19px, 1.8vw, 26px); line-height: 1.22;
  letter-spacing: -.02em; overflow-wrap: break-word;
}
.card-body p { margin: 0 0 12px; color: var(--muted); font-size: 16px; line-height: 1.68; }
.card-link, .text-link {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  margin-top: auto; padding-top: 16px; border-top: 1px solid var(--line);
  color: var(--ink); font: 500 13px/1.35 var(--read);
  transition: color 180ms var(--ease);
}
.card-link:hover, .text-link:hover { color: var(--signal); }
.card-link span:last-child, .text-link span { color: var(--signal); font-size: 17px; }
.text-only { min-height: 0; }

/* ---------- standalone blocks ---------- */
.standalone-grid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 22px; align-items: start; margin-bottom: clamp(26px, 3vw, 40px);
}
.standalone-heading {
  grid-column: 2 / span 8; margin: clamp(20px, 2.4vw, 34px) 0 0;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(23px, 2.6vw, 38px); line-height: 1.16;
  letter-spacing: -.022em; overflow-wrap: break-word;
}
/* One left edge. The export set images at column 3, headings at 2 and text at
   4, so a block of all three read as a staircase rather than as a column.
   Widths still vary, which is what makes it a column and not a box. */
.standalone-text { grid-column: 2 / span 6; margin: 0; color: var(--text); font-size: 18px; line-height: 1.72; }
.standalone-image { grid-column: 2 / span 9; margin: 0; background: var(--mount); }
.standalone-image img { width: 100%; max-height: 480px; object-fit: contain; }
/* Two pictures in one block sit beside each other. Both carried the same
   explicit column, so they stacked as two full-width slabs and the block took
   three screens to say one thing. */
.standalone-grid:has(.standalone-image + .standalone-image) .standalone-image:nth-of-type(odd) {
  grid-column: 2 / span 5;
}
.standalone-grid:has(.standalone-image + .standalone-image) .standalone-image:nth-of-type(even) {
  grid-column: 7 / span 5;
}
/* A shared box so a pair sits level. Without it each picture is only as tall
   as its own aspect ratio makes it, and two side by side read as ragged rather
   than as a pair. `contain` inside the box keeps every picture whole. */
.standalone-grid:has(.standalone-image + .standalone-image) .standalone-image {
  aspect-ratio: 4 / 3;
}
.standalone-grid:has(.standalone-image + .standalone-image) .standalone-image img {
  height: 100%; max-height: none;
}
.standalone-grid > .text-link { grid-column: 2 / span 6; }
.video-frame { position: relative; width: 100%; aspect-ratio: 16/9; margin-top: 20px; background: var(--ink); overflow: hidden; }
.standalone-grid > .video-frame { grid-column: 2 / span 10; margin-top: 0; }
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.source-links { display: flex; flex-wrap: wrap; gap: 12px 22px; margin-top: 20px; }

/* ---------- footer ---------- */
.site-footer {
  padding: var(--band) var(--pad) 28px; background: var(--ink); color: var(--paper);
  display: grid; grid-template-columns: 1.3fr .7fr .7fr; gap: clamp(32px, 4vw, 64px);
}
.footer-brand img { width: 64px; height: 64px; object-fit: contain; filter: brightness(0) invert(1); opacity: .9; }
.footer-brand h2 {
  margin: 24px 0 6px; font-family: var(--display); font-weight: 700;
  font-size: clamp(32px, 3.6vw, 54px); line-height: 1.05; letter-spacing: -.028em;
}
.footer-brand p { margin: 0; color: rgba(255,255,255,.55); }
.footer-links, .footer-social { display: grid; align-content: start; }
.footer-links a, .footer-social a {
  padding: 11px 0; border-bottom: 1px solid rgba(255,255,255,.12);
  font: 500 14px/1.3 var(--read); color: rgba(255,255,255,.82);
  transition: color 180ms var(--ease);
}
.footer-links a:hover, .footer-social a:hover { color: var(--signal-hi); }
.footer-legal {
  grid-column: 1/-1; display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: 14px 20px; margin-top: clamp(32px, 4vw, 56px); padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,.18);
  color: rgba(255,255,255,.46); font-size: 13px;
}

/* ---------- the player ---------- */
.radio-player {
  position: fixed; z-index: 60; left: 0; right: 0; bottom: 0; height: 82px;
  display: grid; grid-template-columns: 240px 1fr 56px; align-items: center;
  gap: 14px; padding: 10px 22px;
  background: var(--mount); border-top: 1px solid var(--line);
  transform: translateY(calc(100% - 16px));
  transition: transform .4s cubic-bezier(.77,0,.18,1);
  box-shadow: 0 -12px 30px rgba(0,0,0,.08);
}
.radio-player:hover, .radio-player.open { transform: translateY(0); }
.player-toggle { display: flex; align-items: center; gap: 12px; border: 0; background: transparent; text-align: left; cursor: pointer; }
.player-icon { width: 42px; height: 42px; border-radius: 50%; background: var(--signal); color: var(--white); display: grid; place-items: center; }
.player-toggle b, .player-toggle small { display: block; }
.player-toggle b { font-size: 15px; font-weight: 700; }
.player-toggle small { margin-top: 3px; color: var(--muted); font-size: 13px; }
.soundcloud-player { height: 56px; overflow: hidden; opacity: 0; pointer-events: none; transition: opacity .3s; }
.radio-player.open .soundcloud-player { opacity: 1; pointer-events: auto; }
.soundcloud-player iframe { width: 100%; height: 120px; border: 0; transform: translateY(-2px); }
.player-close { border: 0; background: transparent; font-size: 26px; font-weight: 200; cursor: pointer; line-height: 1; }

/* ---------- narrower ---------- */
@media (max-width: 1100px) {
  .site-header { grid-template-columns: auto 1fr auto; padding: 0 20px; }
  .primary-nav a:nth-child(n+6) { display: none; }
  .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero-listen { align-self: start; }
  .hero-home { background-size: auto min(300px, 30vw); }
  .standalone-heading { grid-column: 1 / span 10; }
  .standalone-text, .standalone-grid > .text-link { grid-column: 2 / span 9; }
  .standalone-image { grid-column: 1 / span 12; }
  .site-footer { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 760px) {
  body { font-size: 16px; }
  .site-shell { padding-bottom: 72px; }
  .site-header { height: 66px; grid-template-columns: 1fr auto; padding: 0 16px; }
  .brand img { width: 36px; height: 36px; }
  .brand b { font-size: 16px; }
  .brand small { font-size: 9px; }
  .primary-nav, .listen-button { display: none; }
  .hero { margin-top: 66px; padding-top: clamp(40px, 8vw, 64px); }
  .hero-home { background-image: none !important; }
  .hero-content { max-width: none; }
  .menu-grid { grid-template-columns: 1fr; }
  .card-grid, .card-grid.single .archive-card { grid-template-columns: minmax(0, 1fr); }
  .card-grid.single .card-media { min-height: 0; aspect-ratio: 4/3; }
  .page-intro, .section-heading { grid-template-columns: 44px minmax(0, 1fr); gap: 14px; }
  .standalone-grid { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .standalone-heading, .standalone-text, .standalone-image,
  .standalone-grid > .text-link, .standalone-grid > .video-frame { grid-column: 1 / -1; }
  .site-footer { grid-template-columns: 1fr; }
  .radio-player { grid-template-columns: 1fr 44px; }
  .radio-player .soundcloud-player { display: none; }
  .radio-player.open { grid-template-columns: 1fr; height: auto; padding-bottom: 16px; }
  .radio-player.open .soundcloud-player { display: block; grid-column: 1/-1; }
}

/* scroll lock while the sections panel is open; set by site.js */
body.menu-open { overflow: hidden; }
