/* Diwali 2026 — shared design system.
   Both pages load this file. */

:root {
  color-scheme: light;
  --ink: #351d16;
  --ink-soft: #5a4133;
  --red: #8c1d16;
  --gold: #855313;

  /* Glassmorphism. The brightness lift is what makes cream glass readable
     over the dark maroon festival background. */
  --glass: linear-gradient(150deg, rgba(255, 252, 246, .84), rgba(255, 246, 231, .7));
  --glass-blur: blur(26px) saturate(145%) brightness(1.5);
  --glass-edge: rgba(255, 255, 255, .58);
  --glass-shadow: 0 10px 28px rgba(52, 6, 2, .3), inset 0 1px 0 rgba(255, 255, 255, .75);

  --radius: 16px;
  --gap: 7px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  /* A definite height (not just min-height) is what lets the card grid shrink
     to fit instead of sizing to its content and pushing the page into scroll. */
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  color: var(--ink);
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  line-height: 1.35;
  background: #6f110d;
}

/* Fixed backdrop layer. iOS Safari ignores background-attachment:fixed,
   and a real fixed layer is also what the cards' backdrop-filter samples. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: #6f110d url('assets/festival-background.jpg') center top / cover no-repeat;
  z-index: -1;
}

main {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: max(6px, env(safe-area-inset-top)) 11px 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Same pixels as the JPEG above, about half the bytes. Browsers that cannot
   decode WebP never see this rule and keep the JPEG. */
@supports (background-image: image-set(url('assets/festival-background.webp') type('image/webp'))) {
  body::before {
    background-image: image-set(url('assets/festival-background.webp') type('image/webp'),
                                url('assets/festival-background.jpg') type('image/jpeg'));
  }
}

/* ---------- Hero ---------- */

/* The logo artwork is deep red on transparent, so it needs a light surface to
   read against the maroon backdrop. A glass circle keeps it on-theme and
   follows the round medallion of the artwork. Three cards leave room for it
   to run large; the cards keep their content height, only their slack goes. */
.hero {
  flex: none;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(80px, 14.5svh, 130px);
  aspect-ratio: 1;
  padding: 0;
  border: 1px solid var(--glass-edge);
  border-radius: 50%;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
}

/* <picture> is an inline box, so a percentage height on the <img> inside it has
   nothing to resolve against and the image falls back to its intrinsic size,
   overflowing the pill. Giving the wrapper the height restores the chain. */
.hero picture {
  display: block;
  /* Inset from the circle's edge so the medallion's rim clears it. */
  height: 84%;
}

.logo {
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

/* ---------- Card grid ---------- */

.content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.cards {
  flex: 1;
  min-height: 0;
  max-height: 560px;
  display: grid;
  /* Never shorter than its content: the Chopda Pujan card needs a little more
     room than the others for its two session rows. */
  grid-auto-rows: minmax(min-content, 1fr);
  gap: var(--gap);
  align-content: stretch;
}

/* ---------- Card ---------- */

.event-card {
  /* Accent tokens. Everything inside a card that carries the festival colour —
     time badge, date column, selected state — reads these rather than --red, so
     a venue can restate its accent in one place instead of a dozen. */
  --accent: var(--red);
  --accent-rgb: 140, 29, 22;
  --accent-label: #9c3a1c;
  --accent-shadow: rgba(92, 12, 6, .35);

  position: relative;
  display: flex;
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--glass-edge);
  border-radius: var(--radius);
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
}

label.event-card,
.pujan-card { cursor: pointer; }

.event-card.selected {
  border-color: rgba(var(--accent-rgb), .65);
  box-shadow: 0 10px 28px rgba(52, 6, 2, .3), inset 0 0 0 1px rgba(var(--accent-rgb), .45), inset 0 1px 0 rgba(255, 255, 255, .6);
}

.event-card:focus-within { outline: 3px solid #f2c46a; outline-offset: 2px; }

.event-photo {
  flex: 0 0 20%;
  max-width: 92px;
  position: relative;
  display: grid;
  place-items: center;
  background: linear-gradient(150deg, #f6dfb2, #e6c99a);
  color: #9b6624;
  overflow: hidden;
}

.event-photo picture {
  position: absolute;
  inset: 0;
}

.event-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Fades over the blurred placeholder rather than replacing it abruptly. */
  opacity: 0;
  transition: opacity .25s ease;
}

.event-photo.loaded img { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .event-photo img { transition: none; }
}

/* lqip.css sets a blurred data-URI preview per event on top of this gradient.
   Scaled up from ~20px, so it reads as the photo's colours, not its detail. */
.event-photo { background-size: cover; background-position: center; }

.photo-motif { font-size: 26px; }

/* Body + date rail sit side by side; in the banner layout they sit below the photo. */
.card-main {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
}

.event-body {
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 8px 10px 12px;
}

/* Badge rides on the photo so it costs the text column no vertical space. */
.badge {
  position: absolute;
  left: 6px;
  top: 6px;
  z-index: 2;
  padding: 2px 6px;
  border-radius: 7px;
  background: rgba(255, 251, 243, .88);
  box-shadow: 0 1px 3px rgba(60, 10, 0, .25);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: .05em;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--gold);
}

/* Only the first line has to clear the checkbox corner. */
h2 {
  padding-right: 34px;
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: clamp(15px, 4.4vw, 19px);
  line-height: 1.1;
  margin: 0;
}

.title-name, .title-city { white-space: nowrap; }

.subtitle {
  font-size: 10.5px;
  color: var(--ink-soft);
  margin: 0;
}

/* The time reads as a badge, matching the Chopda Pujan session segments so the
   the cards share one visual language whether the time is fixed or chosen. */
/* A fixed time is an already-chosen time, so it wears the same filled badge the
   selected Chopda Pujan session does — same fill, height and radius. */
.event-time {
  align-self: flex-start;
  display: flex;
  align-items: center;
  min-height: 36px;
  margin: 7px 0 0;
  padding: 4px 14px;
  border: 1px solid var(--accent);
  border-radius: 9px;
  background: var(--accent);
  box-shadow: 0 2px 6px var(--accent-shadow);
  color: #fff6e6;
  font-size: 12.5px;
  font-weight: 700;
}

.address {
  font-size: 9.5px;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 11px 0 0;
  line-height: 1.35;
}

.address span { display: block; }

/* ---------- Date accent ----------
   Month and weekday sit at the top. The numeral is an oversized layer rising
   from the bottom edge, cropped by the rail so it reads as depth rather than a
   boxed badge. It is sized against the rail's own box (container query units),
   so it fills each card whatever height the grid gives it. */

.date-rail {
  /* A layer, not a column: out of the flow so the title and address get the
     full card width, sitting behind text that is short enough not to reach it. */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 104px;
  /* No z-index here: a stacking context would trap the checkbox below the body,
     which sits at z-index 1. The accent's own content has no z-index and so
     paints under the body; the checkbox lifts itself above it. */
  pointer-events: none;
  container-type: size;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Bottom-anchored: the label line rides directly on top of the numeral. */
  justify-content: flex-end;
  padding: 0 4px 0 0;
  overflow: hidden;
  color: var(--accent);
  text-align: center;
}

.date-rail input[type=checkbox] {
  position: absolute;
  top: 7px;
  right: 8px;
  margin: 0;
  width: 22px;
  height: 22px;
  z-index: 2;
  accent-color: var(--accent);
  cursor: pointer;
  pointer-events: auto;
}

/* The one celebration with a fireworks finale gets a burst washed in behind its
   date column. Generated vector rather than a photo crop: it stays crisp at any
   density, weighs 10 KB, already falls off at its own edges so it needs no mask,
   and its palette is tuned to the card instead of fighting it. */
.has-fireworks::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--fireworks) 58% 30% / 155% auto no-repeat;
  opacity: .85;
  pointer-events: none;
}

.date-num { position: relative; z-index: 1; }

.date-labels {
  flex: none;
  z-index: 2;
  margin-bottom: 3px;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(255, 251, 243, .78);
  box-shadow: 0 1px 3px rgba(60, 10, 0, .16);
  font-size: 8px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: .01em;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--accent-label);
}

.date-num {
  flex: none;
  /* Centred under the date badge, so a single digit sits square beneath it
     rather than pushed off to one side. */
  align-self: center;
  /* Overhang the rail's bottom edge; overflow:hidden does the cropping. */
  margin-bottom: -.1em;
  /* Lining figures are the whole point of this stack: Georgia's default
     old-style figures give 3, 4, 7 and 9 descenders and 6, 8 ascenders, so
     every card cropped to a different height. Iowan (Apple), Palatino
     (Windows) and Times New Roman all sit on one cap height and baseline, so
     8, 10, 14 and 31 now crop identically. */
  font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Times New Roman', serif;
  font-variant-numeric: lining-nums;
  font-feature-settings: 'lnum' 1;
  font-weight: 600;
  font-size: clamp(46px, 13vw, 76px);
  font-size: min(100cqh, 94cqw);
  /* Default tracking leaves a gap between the digits at this size, so "10"
     reads as two marks instead of one date. */
  letter-spacing: -.06em;
  line-height: .78;
  opacity: .5;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .4);
}

/* ---------- Chopda Pujan segmented session toggle ---------- */

.session-toggle {
  display: flex;
  gap: 5px;
  margin: 5px 0 0;
  /* Stop the segments stretching under the date accent. */
  max-width: calc(100% - 96px);
}

.session {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 3px 2px;
  border: 1px solid rgba(var(--accent-rgb), .4);
  border-radius: 9px;
  background: rgba(255, 255, 255, .5);
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
}

.session span {
  /* Sized so the full "4 PM – 6 PM" fits a half-width segment from 361px up. */
  font-size: 12px;
  font-weight: 700;
  line-height: 1.15;
}

.session input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.session.selected {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff6e6;
  box-shadow: 0 2px 6px var(--accent-shadow);
}

/* Chopda Pujan's two sessions stack as rows: "6:30 PM – 7:30 PM" is too wide
   for side-by-side segments on a phone. The session name is a small caps
   label; the time is what reads first. */
/* Sized to its text like the other time badges, not stretched across the
   card; both rows take the width of the wider one. */
.pujan-card .session-toggle { flex-direction: column; gap: 4px; align-self: flex-start; width: max-content; max-width: calc(100% - 92px); }
.pujan-card .session { min-height: 0; padding: 3px 11px; gap: 0; align-items: flex-start; }
.pujan-card .session strong {
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.15;
  opacity: .8;
}
.pujan-card .session span { font-size: 11.5px; font-weight: 800; line-height: 1.15; }

/* "Sharda (Chopda) Pujan · Dallas" is the longest title; below 390px it steps
   down so it still fits on one line. */
@media (max-width: 389px) { .pujan-card h2 { font-size: 3.9vw; } }

/* The mandir heads the address block, a shade stronger than the street lines. */
.address .mandir { font-weight: 700; }

.session:focus-within { outline: 3px solid #f2c46a; outline-offset: 1px; }

/* ---------- Help ---------- */

/* A centred pill rather than a disclosure triangle: expanding help inline
   pushed the card grid and broke the one-screen fit, so it opens as a dialog. */
.help-row {
  flex: none;
  display: flex;
  justify-content: center;
}

.help-button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 4px 13px;
  border: 1px solid rgba(255, 233, 200, .42);
  border-radius: 999px;
  background: rgba(58, 8, 5, .32);
  color: #ffeacb;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  text-shadow: 0 1px 4px rgba(40, 2, 0, .85);
  cursor: pointer;
}

.help-button .ico-info {
  flex: none;
  width: 15px;
  height: 15px;
}

.help-button:focus-visible { outline: 3px solid #f2c46a; outline-offset: 2px; }

a { color: #ffd9a0; }

.no-script { padding: 16px; color: #ffe6c2; }

/* ---------- Action bar ---------- */

.action-bar {
  flex: none;
  position: sticky;
  bottom: 0;
  z-index: 10;
  margin-top: var(--gap);
  padding: 9px 11px max(9px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--glass-edge);
  background: linear-gradient(180deg, rgba(255, 249, 238, .7), rgba(255, 244, 226, .82));
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}

.action-inner {
  max-width: 538px;
  margin: 0 auto;
}

.selection-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 22px;
  margin-bottom: 5px;
  font-size: 12px;
}

.selection-summary button {
  border: 0;
  background: transparent;
  color: var(--red);
  font-size: 11px;
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 2px;
}

.action-buttons { display: flex; gap: 8px; }

.action-buttons button {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 44px;
  padding: 10px 8px;
  border: 1px solid var(--red);
  border-radius: 11px;
  background: var(--red);
  color: #fff;
  font: inherit;
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
}

/* Two calendars, side by side. The device decides which is filled; both stay
   tappable because user-agent detection misfires on tablets and in-app
   browsers, and neither path works on the other's platform. */
.action-buttons button {
  gap: 7px;
  font-size: 12.5px;
  padding: 10px 6px;
}

.action-buttons .ico { width: 17px; height: 17px; flex: none; }

.g-chip {
  flex: none;
  width: 19px;
  height: 19px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #fff;
}

.g-chip svg { width: 13px; height: 13px; display: block; }

/* Phones get the one calendar they can actually use. */
.show-apple #gcal,
.show-google #download { display: none; }

/* Where the device is unknown, both are offered with the file path leading,
   since an .ics works with Apple Calendar, Outlook and Google Calendar on the
   web, while the Google links only ever reach Google. */
.show-both #gcal {
  background: transparent;
  color: var(--red);
  font-weight: 600;
}

/* Sheet listing one Google Calendar link per selected event. */
/* Both dialogs live as direct children of <body>. They cannot sit inside
   .action-bar: its backdrop-filter makes it the containing block for fixed
   descendants, which pinned the scrim to the bar's own 89px instead of the
   viewport. Computed position stays "fixed" either way, so only a measured
   box catches it. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(40, 3, 0, .5);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.sheet-panel {
  width: 100%;
  max-width: 460px;
  max-height: min(84svh, 640px);
  overflow-y: auto;
  padding: 18px;
  border-radius: 20px;
  background: #fffaf0;
  box-shadow: 0 18px 52px rgba(40, 3, 0, .45);
}

.sheet-panel h3 {
  margin: 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: 20px;
}

.sheet-note { margin: 4px 0 12px; font-size: 12px; color: var(--ink-soft); }

/* Scoped to a class, not to `.sheet-panel p`, which would outrank .sheet-note. */
.sheet-text {
  margin: 9px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-soft);
}

.sheet-text strong { color: var(--ink); font-weight: 650; }

/* Numbered steps, one instruction per line. The panel shows the set for the
   device it is on; a desktop shows the picker above and neither set until the
   visitor chooses, because there we cannot know which calendar they use. */
.sheet-prompt {
  margin: 13px 0 7px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--ink);
}

.help-picker { display: flex; gap: 8px; margin-bottom: 4px; }

.help-picker button {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 44px;
  padding: 10px 6px;
  border: 1px solid var(--red);
  border-radius: 11px;
  background: transparent;
  color: var(--red);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

.help-picker button[aria-pressed=true] {
  background: var(--red);
  color: #fff;
  font-weight: 650;
}

.help-picker .ico { flex: none; width: 17px; height: 17px; }

.help-steps {
  margin: 13px 0 0;
  padding-left: 21px;
  display: grid;
  gap: 7px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-soft);
}

.help-steps::marker, .help-steps li::marker {
  color: var(--red);
  font-weight: 700;
}

.help-steps strong { color: var(--ink); font-weight: 650; }

#gcal-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }

.gcal-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 11px;
  border: 1px solid #e3cda6;
  border-radius: 11px;
  background: #fffdf8;
}

.gcal-item strong { display: block; font-size: 13.5px; font-weight: 650; }
.gcal-item span { display: block; font-size: 11px; color: var(--ink-soft); }
.gcal-item .gcal-when { margin-top: 1px; font-weight: 600; color: var(--ink); }

.gcal-add {
  flex: none;
  min-width: 62px;
  min-height: 38px;
  display: grid;
  place-items: center;
  padding: 0 14px;
  border-radius: 9px;
  background: var(--red);
  color: #fff;
  font-size: 13px;
  font-weight: 650;
  text-decoration: none;
}

.gcal-item.added { border-color: #b9d3ae; background: #f4faf0; }
.gcal-item.added .gcal-add { background: #5d7f4e; }
.gcal-item.added .gcal-add::after { content: ' ✓'; }

.sheet-done {
  width: 100%;
  margin-top: 12px;
  min-height: 44px;
  border: 1px solid var(--red);
  border-radius: 11px;
  background: transparent;
  color: var(--red);
  font: inherit;
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
}

button:disabled { opacity: .5; }

button:focus-visible, a:focus-visible, summary:focus-visible {
  outline: 3px solid #f2c46a;
  outline-offset: 2px;
}

#download-status { font-size: 11px; margin: 5px 0 0; }
#download-status:empty { display: none; }

[hidden] { display: none !important; }

/* ---------- Narrow phones ---------- */

@media (min-width: 361px) and (max-width: 389px) {
  .session span { font-size: 10.75px; }
}

@media (max-width: 360px) {
  .event-photo { flex-basis: 18%; }
  .date-rail { width: 92px; }
  .event-body { padding: 7px 8px; }
  .session { font-size: 10.5px; }
  /* The full "4 PM – 6 PM" has to fit a half-width segment on the narrowest phones. */
  .session span { font-size: 9px; letter-spacing: -.01em; }
  .pujan-card .session span { font-size: 11px; }
  .pujan-card .session { padding: 3px 8px; }
  /* "SATURDAY · OCT" is the widest label and has to fit the narrow rail too. */
  .date-labels { font-size: 7px; letter-spacing: 0; padding: 2px 5px; }
  .event-time { padding: 4px 8px; font-size: 11.5px; }
}

/* ---------- Short viewports ----------
   The no-scroll layout is sized for iPhone 15/16/17-class screens. Below that
   there genuinely is not room, so release the fixed height and let the page
   scroll rather than squeezing the cards until their text clips. */

@media (max-height: 700px) {
  body { height: auto; min-height: 100svh; }
  .hero { height: 62px; }
  .cards { grid-auto-rows: auto; max-height: none; }
  .event-card { min-height: 112px; }
  main { padding-bottom: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
}
