/* GCSV — ledenapp.
 *
 * The app's own styling lives inline on the markup in index.html's <template>,
 * exactly as the design was authored. This file carries the page-level rules:
 * a full-viewport mobile app that fills the screen when installed to a home
 * screen, and sits in a phone-width column when opened on a desktop.
 *
 * Nothing here loads from anywhere but this origin. The typefaces come from
 * assets/fonts/fonts.css, which is linked before this file; there is no font
 * CDN, no analytics beacon and no third-party stylesheet, because every one of
 * those would hand a member's IP address to somebody they never agreed to.
 */

/* ── page ──────────────────────────────────────────────────────────────── */

/* An id selector outranks the browser's own [hidden] rule, so anything given
   a background or a display here would ignore the attribute. Settle it once,
   for every element on the page. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  /* Same cream as the app: on iOS the area behind the status bar and home
     indicator is painted by the page, so a different colour here shows up as
     bands at the top and bottom. */
  background: #f5f2e9;
  overscroll-behavior: none;   /* no rubber-band bounce past the app */
}

body {
  /* Keep the app off the browser's own text-size fiddling on iOS, and stop
     double-tap zoom. Pinch-zoom is disabled in the viewport meta. */
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/* The app frame — the same structure as the koekkoek apps, on purpose.

   html and body are 100% tall and do not scroll; #app is a 100%-tall block
   in NORMAL document flow, and the screens inside it scroll. That is all.

   The strip of background that used to sit under the tab bar on an iPhone
   was never this element's fault, and none of the four rewrites of it
   changed anything: the viewport iOS handed the page was 59pt shorter than
   the screen, because of the black-translucent status bar style in
   index.html. That meta is now "default" — see the note beside it — and the
   viewport is the full glass. A 100%-tall block then fills it. The template
   pads its own content off the home indicator with env(safe-area-inset-*). */
html, body {
  overflow: hidden;
}

#app {
  position: relative;
  width: 100%;
  height: 100%;
  background: #f5f2e9;
  overflow: hidden;
}

/* On anything wider than a phone, sit in a centred column so the app still
   reads as an app rather than a stretched page. */
@media (min-width: 620px) {
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    background: #e8e3d5;
  }
  #app {
    width: 420px;
    height: min(880px, var(--app-h, 100vh));
    border-radius: 26px;
    box-shadow: 0 24px 60px rgba(38, 34, 26, .18), 0 0 0 1px rgba(38, 34, 26, .1);
  }
}

a { color: #2e6584; }
a:hover { color: #1f4459; }

::-webkit-scrollbar { width: 0; height: 0; }

textarea::placeholder,
input::placeholder { color: #a39c8c; }

/* Stop iOS zooming the page when a text field takes focus — anything under
   16px triggers it. The template's own sizes are already at or above this. */
input, textarea, select { font-size: 16px; }

/* A disabled control has to look disabled; the erase confirmation leans on
   this to say "not yet" without a second sentence. */
button[disabled] { opacity: .45; cursor: not-allowed; }

@keyframes gcsvPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(46, 101, 132, .45); }
  70%      { box-shadow: 0 0 0 16px rgba(46, 101, 132, 0); }
}

@keyframes gcsvSpin {
  to { transform: rotate(360deg); }
}

/* ── install affordances ───────────────────────────────────────────────── */

/* Shown only when the browser fires beforeinstallprompt (Android, desktop
   Chrome). app.js unhides it and drives the prompt. */
#install {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 88px);
  z-index: 80;
  height: 46px;
  padding: 0 20px;
  border: none;
  border-radius: 999px;
  background: #26221a;
  color: #f5f2e9;
  font: 700 14px 'Instrument Sans', sans-serif;
  box-shadow: 0 8px 24px rgba(38, 34, 26, .32);
  cursor: pointer;
}

/* iOS has no install prompt, so Safari users get told where the button is. */
#ios-hint {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  z-index: 80;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: 14px;
  background: #26221a;
  color: #f5f2e9;
  font: 500 13px/1.45 'Instrument Sans', sans-serif;
  box-shadow: 0 8px 24px rgba(38, 34, 26, .32);
}

/* The message is one text flow, not a row of flex items — otherwise every
   word between the pills becomes its own column. */
#ios-hint p { margin: 0; flex: 1; min-width: 0; }

#ios-hint b { font-weight: 700; }

#ios-hint span {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 5px;
  background: rgba(245, 242, 233, .16);
  font-weight: 600;
}

/* Same circle as the toast's close button, and centred the same way: no
   padding of the browser's own, flex centring, and a drawn cross rather than
   a × glyph that sits high in its line box. */
#ios-hint-close {
  margin-left: auto;
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(245, 242, 233, .16);
  color: #f5f2e9;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

#ios-hint-close svg {
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

/* ── the dynamic viewport ─────────────────────────────────────────────────
   Only the desktop frame needs a height at all: it is a floating 420px card
   in the middle of a window, so there are no edges to pin it to and it has to
   be told how tall to be. dvh is the better number there than vh, and the
   var() fallback chain above still covers browsers that have neither.

   The phone layout is deliberately absent from this block. It is pinned by
   its four edges and must not be given a height by anything — a height
   declaration would win over bottom:0 and hand the tab bar back the gap this
   whole file has now chased twice. */
@supports (height: 100dvh) {
  @media (min-width: 620px) {
    #app { height: min(880px, var(--app-h, 100dvh)); }
  }
}
