/* ============================================================
   File:        dashboard.css
   Project:     StudioFlow (Grace Aerobics & Fitness Center)
   Developer:   Janvi Vakhariya — V Techno Labs
   Created:     2026-08-31  (updated 2026-09-07)
   Purpose:     The Admin Dashboard design system — banner, quick tiles, class
                rows, money cards, member tiles and the instructor list.
   Copyright:   © 2026 V Techno Labs. All rights reserved.
                Proprietary software developed by V Techno Labs.
   ============================================================

   Lives in its own stylesheet rather than an inline <style> block on purpose.
   Any at-rule here -- @container, @media, @supports -- would have to be written
   @@ inside a .cshtml, and one missed escape is a build error nobody reads
   twice. A stylesheet has no Razor parser in front of it.

   Everything is prefixed sf-dash- so it cannot collide with site.css, which
   owns the app shell (sf-app, sf-appbar, sf-tabbar) and every other screen.

   Loaded AFTER bootstrap.min.css, but never relying on that. Bootstrap Reboot
   styles bare elements -- `a`, `button` -- at 0,0,1, so any reset here has to
   out-specify it rather than merely follow it. See the anchor reset below,
   which is where that went wrong once already.

   Three things this file deliberately does NOT do:

   1. It draws no coloured square behind a quick-access tile. The supplied
      artwork for Users, Aerobics, Yoga and Dance is already a finished 64x64
      rounded tile with its own fill, so a gradient here would nest a coloured
      box inside a coloured box. The six .sf-dash-tile--* gradient rules the
      design shipped with are gone for that reason.

   2. It does not restate the activity colours. Aerobics, Yoga and Dance are
      defined once, in site.css :root as --activity-aerobics / -yoga / -dance,
      and read from there below. One list, so a batch chip and a plan badge can
      never drift apart.

   3. It does not reserve room for the fixed bars when it is inside the app
      shell. .sf-app already pads the body by --appbar-h and --tabbar-h; adding
      the same numbers again would leave a second empty bar's worth of gap.
   ============================================================ */

.sf-dash {
  /* The banner photo. Swap it for a different crop by pointing this at another
     file, e.g. --sf-dash-photo: url("/img/banner-2027.png"); nothing else in
     this stylesheet needs touching. If the file is ever missing, put
     .sf-dash-banner-fallback on the banner element (see that rule below) — a
     designed gradient in the studio's own colours, not an empty dark box. */
  --sf-dash-photo: url("/img/wings.png");

  --sf-dash-wing: linear-gradient(90deg,#43a047,#d4b91e,#f57c00,#e53957,#c2185b,#7e57c2,#5c6f91);
  --sf-dash-ground: #ffffff;
  /* Muted deepened from #6d6b58, which measured 4.05:1 against the darkest
     part of the shared ball-pit ground -- under the 4.5:1 minimum for any
     muted line that sits on the ground rather than inside a card. #615F4E
     measures 4.85:1 there and 6.45:1 on white. Deepening the ink was the fix,
     not a panel behind the text. */
  --sf-dash-ink: #2b2a1f; --sf-dash-muted: #615F4E;
  --sf-dash-glass: #ffffff; --sf-dash-glass-edge: rgba(43,42,31,.08);
  --sf-dash-glass-line: rgba(43,42,31,.12);
  --sf-dash-good: #1d7a3f; --sf-dash-warn: #9a5b00; --sf-dash-bad: #c62828;

  /* The three class types, read from the one list in site.css. The -ink pair
     comes with them: the violet needs dark text to stay readable, the teal and
     the amber already carry their own. */
  --sf-dash-aer: var(--activity-aerobics, #17a89a);
  --sf-dash-yog: var(--activity-yoga, #f08a1d);
  --sf-dash-dan: var(--activity-dance, #9d76e8);
  --sf-dash-aer-ink: var(--activity-aerobics-text, #1e293b);
  --sf-dash-yog-ink: var(--activity-yoga-text, #1e293b);
  --sf-dash-dan-ink: var(--activity-dance-text, #241338);

  --sf-dash-radius: 20px; --sf-dash-tap: 48px;

  /* Bound to the app's own bar heights, so a standalone use of .sf-dash still
     clears them. Inside .sf-app they are zeroed below — see note 3 above. */
  --sf-dash-top-bar: var(--appbar-h, 56px);
  --sf-dash-bottom-bar: var(--tabbar-h, 64px);

  box-sizing: border-box; max-width: 640px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 16px;
  padding: calc(var(--sf-dash-top-bar) + 14px) 16px calc(var(--sf-dash-bottom-bar) + 26px + env(safe-area-inset-bottom, 0px));
  background: var(--sf-dash-ground);
  color: var(--sf-dash-ink);
  font-family: "Archivo", system-ui, sans-serif; font-size: 15px; line-height: 1.5;

  /* No container-type. The design set inline-size for a query at the foot of
     the file that widened quick access to six columns; that query is gone (see
     the note down there), so declaring a container here would only impose
     layout and inline-size containment for nothing to read. */
  -webkit-tap-highlight-color: transparent;
}

/* Inside the app shell the layout has already done all three jobs: .sf-app pads
   the body past both fixed bars, .sf-content supplies the 1rem side gutter and
   caps the column at 640px, and .sf-frame paints the one shared ground. This
   screen used to layer two coloured washes of its own over that ground, which
   made the app's first page the only page that did not match the rest; it now
   takes the shared background unchanged. Repeating any of the three here would
   double the gap or hide the ground behind a white block, so this rule stands
   them all down. */
.sf-app .sf-dash {
  --sf-dash-top-bar: 0px;
  --sf-dash-bottom-bar: 0px;
  padding-left: 0; padding-right: 0;
  background: transparent;
}

.sf-dash *, .sf-dash *::before, .sf-dash *::after { box-sizing: border-box; }

/* Every anchor on this screen is a component -- a tile, a class row, a money
   card -- so none of them may arrive underlined and link-blue.

   The :where() sits on the ANCHOR, not on .sf-dash, and that placement is the
   whole point. Written the other way round, :where(.sf-dash a), the selector
   scores 0,0,0 -- :where() contributes nothing -- and loses to Bootstrap
   Reboot's own `a { text-decoration: underline }` at 0,0,1, which is what left
   this dashboard underlined in link-blue no matter what order the sheets load
   in. Source order cannot rescue a selector that is simply weaker.

   `.sf-dash :where(a)` scores 0,1,0: past Bootstrap, and level with a single
   component class. Level matters as much as past. Every rule below that paints
   an anchor -- .sf-dash-money-card, .sf-dash-mtile, .sf-dash-tile -- is also
   0,1,0 and comes later in this file, so it still wins its own colour. A blunt
   `.sf-dash a` at 0,1,1 would have beaten all of them and repainted the money
   cards in the ink colour. */
.sf-dash :where(a) { color: inherit; text-decoration: none; }
.sf-dash :focus-visible { outline: 2px solid #c2185b; outline-offset: 2px; }
.sf-dash-ico { display: inline-block; width: 20px; height: 20px; flex: none; }
.sf-dash-go { display: inline-block; width: 16px; height: 16px; flex: none; opacity: .7; }

/* ---------- header banner: the ONLY place the photo appears ---------- */
.sf-dash-banner {
  position: relative; overflow: hidden;
  min-height: 190px; padding: 18px 18px 16px;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 2px;
  border-radius: 24px; border: 1.5px solid rgba(255,255,255,.4);
  background:
    linear-gradient(180deg, rgba(32,22,44,.05) 22%, rgba(32,22,44,.6) 78%, rgba(32,22,44,.78) 100%),
    var(--sf-dash-photo) center 24% / cover no-repeat;
  box-shadow: 0 18px 36px -18px rgba(194,24,91,.5);
  color: #fff;
}
.sf-dash-banner::after { content: ""; position: absolute; inset: auto 0 0 0; height: 5px; background: var(--sf-dash-wing); }
/* The avatar and the date on one line, the circle centred against the text
   rather than sitting above it. Replaces the design's "Hello, Admin" line:
   the greeting said nothing the "Signed in as ... · owner" line underneath
   does not already say, and the initial says whose screen this is at a glance
   and in less room. */
.sf-dash-banner-id { display: flex; align-items: center; gap: 12px; }

/* One solid circle in the studio's own pink -- var(--brand-pink) from site.css,
   the same colour the section links and the progress ring already use. Fixed,
   never derived from the name: an avatar that changed colour between two people
   or between two loads reads as a different account. White on #C2185B measures
   5.87:1, past the 4.5:1 this letter needs at 20px.

   The ring is what keeps it legible over the photograph, which is dark in some
   crops and bright in others. */
.sf-dash-avatar {
  flex: none;
  display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--brand-pink, #c2185b);
  border: 2px solid rgba(255,255,255,.55);
  box-shadow: 0 4px 12px -4px rgba(20,10,35,.6);
  color: #fff; font-size: 20px; font-weight: 800; line-height: 1;
  text-transform: uppercase; user-select: none;
}

/* The two stacked lines beside the circle. min-width: 0 so a long name or a
   long date ellipsises inside the flex row instead of pushing the avatar out. */
.sf-dash-banner-idtext { min-width: 0; }

.sf-dash-banner-date { margin: 0; font-size: 25px; font-weight: 800; letter-spacing: -.02em; line-height: 1.15; text-shadow: 0 1px 10px rgba(0,0,0,.4); }

/* Only the class-count pill is left on this row, so it keeps the right-hand
   position it held when the signed-in line sat opposite it. */
.sf-dash-banner-row { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 8px; }

/* 16px, up from the design's 13px. It sits directly under a 25px date now
   rather than off on its own row, so it can carry more weight without
   competing -- and it is the line that says whose account this is.
   margin is restated because Bootstrap Reboot gives every <p> a 1rem bottom,
   which would have pushed the pill row down by a whole line. The shadow
   matches the date's, so both stay readable over a bright patch of photo. */
.sf-dash-banner-meta {
  margin: 3px 0 0;
  font-size: 16px; font-weight: 600;
  color: rgba(255,255,255,.9);
  text-shadow: 0 1px 10px rgba(0,0,0,.4);
}
.sf-dash-banner-meta strong { color: #fff; font-weight: 800; }
.sf-dash-banner-pill {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 12px; border-radius: 999px;
  background: rgba(255,255,255,.2); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.4);
  font-size: 12px; font-weight: 800; white-space: nowrap;
}

/* The banner with no photograph behind it. Deliberately not an empty dark box:
   the studio's own colours, layered the way the photo crop sits, so a missing
   file still reads as a designed header rather than a fault.

   To go back to a real photo: drop the .sf-dash-banner-fallback class from the
   <header> in AdminDashboard.cshtml and point --sf-dash-photo above at the file
   (e.g. --sf-dash-photo: url("/img/wings.png")). Nothing else changes. */
.sf-dash-banner-fallback {
  background:
    linear-gradient(180deg, rgba(32,22,44,.10) 18%, rgba(32,22,44,.62) 76%, rgba(32,22,44,.82) 100%),
    radial-gradient(120% 90% at 12% 8%, #17a89a 0%, rgba(23,168,154,0) 62%),
    radial-gradient(110% 85% at 92% 0%, #f08a1d 0%, rgba(240,138,29,0) 58%),
    linear-gradient(150deg, #c2185b 0%, #7b519b 52%, #241c33 100%);
}

/* ---------- section heading (outside cards, like a real app) ---------- */
.sf-dash-h { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 2px 2px -6px; }
.sf-dash-h-title { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: .01em; }
.sf-dash-h-link { position: relative; font-size: 13px; font-weight: 800; color: #c2185b; white-space: nowrap; }
.sf-dash-h-link:active { text-decoration: underline; text-underline-offset: 3px; }

/* "All batches", "Payments", "Directory", "Payroll view" are 13px of text --
   about 18px tall, well under the 44px a thumb needs. The design gave them a
   24px min-height, which is still short and, on a baseline-aligned flex row,
   growing the box any further would push the heading off its own line.
   An absolutely positioned overlay adds the reach with no layout at all. */
.sf-dash-h-link::after { content: ""; position: absolute; inset: -13px -10px; }

/* ---------- glass card shell ---------- */
.sf-dash-card {
  background: var(--sf-dash-glass);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  border: 1.5px solid var(--sf-dash-glass-edge);
  border-radius: var(--sf-dash-radius);
  box-shadow: 0 14px 30px -16px rgba(194,24,91,.4);
  padding: 16px; position: relative; overflow: hidden;
}

/* The one empty-state voice for the whole screen: no classes today, no
   instructor figures yet, no batches set up. */
.sf-dash-note { margin: 0; font-size: 14px; color: var(--sf-dash-muted); }

/* ---------- quick access ----------
   Three columns, two rows: Devices, Users, Plans, then Aerobics, Yoga, Dance.
   The tile itself is only a box that positions the artwork and its label — the
   colour lives in the artwork, never here. */
.sf-dash-tiles { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 10px; }
.sf-dash-tile {
  min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  min-height: 84px; padding: 10px 6px; border-radius: 18px;
  color: var(--sf-dash-ink);
  font-size: 13px; font-weight: 800; text-align: center;
}
.sf-dash-tile:nth-child(odd)  { transform: rotate(-1.2deg); }
.sf-dash-tile:nth-child(even) { transform: rotate(1.2deg); }
.sf-dash-tile:active { transform: translateY(1px); }

/* The supplied artwork, placed as the tile. 64x64 with the artwork's own 15px
   corner, so the shadow hugs the rounded square rather than a bounding box.
   Never recoloured and never masked: a mask reads only alpha, and this artwork
   is opaque across the whole 64x64, so it would paint as a solid block. */
.sf-dash-tile-img {
  display: block; width: 64px; height: 64px; flex: none;
  border-radius: 15px;
  border: 1px solid rgba(255,255,255,.3);
  box-shadow: 0 10px 20px -10px rgba(194,24,91,.45);
}

/* Two of the six — Devices and Plans — are supplied as stroke-only glyphs meant
   to be painted through a CSS mask, not as finished tiles. They get the square
   the artwork does not carry, in the colour DashboardIcons already assigns
   them, at exactly the same size as the finished tiles beside them. */
.sf-dash-tile-box {
  display: inline-flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; flex: none;
  border-radius: 15px; color: #fff;
  border: 1px solid rgba(255,255,255,.3);
  box-shadow: 0 10px 20px -10px rgba(194,24,91,.45);
}
.sf-dash-tile:active .sf-dash-tile-img,
.sf-dash-tile:active .sf-dash-tile-box { filter: brightness(.94); }
.sf-dash-tile-label { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- today's classes: ring + batches ---------- */
.sf-dash-ringrow { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.sf-dash-ring {
  --sf-dash-ring-val: 0;  /* % of today's batches marked — set inline by the view */
  width: 62px; height: 62px; flex: none; border-radius: 50%;
  background:
    radial-gradient(closest-side, rgba(80,60,110,.0) 0 62%, transparent 62% 100%),
    conic-gradient(#c2185b calc(var(--sf-dash-ring-val) * 1%), rgba(43,42,31,.14) 0);
  display: grid; place-items: center;
}
.sf-dash-ring::before {
  content: attr(data-val);
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255,255,255,.92);
  display: grid; place-items: center;
  font-size: 13px; font-weight: 800; color: #c2185b;
}
.sf-dash-ring-text { min-width: 0; }
.sf-dash-ring-line1 { margin: 0; font-size: 15px; font-weight: 800; }
.sf-dash-ring-line2 { margin: 1px 0 0; font-size: 13px; color: var(--sf-dash-muted); }

.sf-dash-batch {
  display: grid; grid-template-columns: 52px minmax(0,1fr) auto;
  grid-template-areas: "time main counts" "time meter meter";
  align-items: center; column-gap: 12px; row-gap: 7px;
  padding: 11px 0; border-top: 1px solid var(--sf-dash-glass-line);
}
.sf-dash-batch-time {
  grid-area: time; align-self: start; display: flex; flex-direction: column; align-items: center; justify-content: center;
  width: 52px; min-height: 46px; border-radius: 14px;
  font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1;
  box-shadow: 0 6px 12px -7px rgba(20,10,35,.7);

  /* A class type with no rule of its own still gets a readable chip rather than
     an unstyled one — the same fallback the activity badge has always had. */
  background: var(--sf-dash-aer); color: var(--sf-dash-aer-ink);
}
.sf-dash-batch-time small { font-size: 10px; font-weight: 700; letter-spacing: .06em; }

/* The chip's fill and its ink both come from the one activity list. The ink is
   read rather than hard-coded to white: at 15px this is small text, so white on
   the violet would sit at 3.4:1, under the 4.5:1 it needs. */
.sf-dash-batch--aerobics .sf-dash-batch-time { background: var(--sf-dash-aer); color: var(--sf-dash-aer-ink); }
.sf-dash-batch--yoga     .sf-dash-batch-time { background: var(--sf-dash-yog); color: var(--sf-dash-yog-ink); }
.sf-dash-batch--dance    .sf-dash-batch-time { background: var(--sf-dash-dan); color: var(--sf-dash-dan-ink); }

/* A cancelled class is greyed rather than coloured: showing it in its activity
   colour would read as a class that ran. */
.sf-dash-batch--off .sf-dash-batch-time { background: #5f5d4d; color: #fff; }
.sf-dash-batch--off .sf-dash-batch-name { text-decoration: line-through; }

.sf-dash-batch-main { grid-area: main; min-width: 0; }
.sf-dash-batch-name { display: block; font-size: 15px; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-dash-batch-sub { display: block; font-size: 12px; color: var(--sf-dash-muted); }
.sf-dash-batch-counts { grid-area: counts; text-align: right; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sf-dash-batch-counts .is-present { color: var(--sf-dash-good); }
.sf-dash-batch-counts .is-absent { color: var(--sf-dash-muted); font-weight: 600; }
.sf-dash-batch-counts .is-unmarked { color: var(--sf-dash-warn); }
.sf-dash-batch-counts .is-open { color: #c2185b; }
.sf-dash-batch-counts .is-off { color: var(--sf-dash-muted); font-weight: 600; }

.sf-dash-meter { grid-area: meter; position: relative; height: 6px; border-radius: 999px; background: rgba(43,42,31,.12); overflow: hidden; }
.sf-dash-meter::before { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--sf-dash-fill, 0%); border-radius: 999px; background: var(--sf-dash-wing); }

/* A batch with no capacity has nothing to measure against, so the view omits
   the meter entirely rather than drawing an honest-looking 0%. The grid row it
   sat in collapses on its own — a grid row with no item has no height — so
   nothing else needs saying here. */

/* ---------- money ---------- */
.sf-dash-money { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 12px; }
.sf-dash-money-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 2px; min-height: 116px; padding: 14px;
  border-radius: var(--sf-dash-radius); border: 1.5px solid rgba(255,255,255,.35);
  box-shadow: 0 14px 28px -14px rgba(20,10,35,.65); color: #fff;
}
.sf-dash-money-card--in  { background: linear-gradient(155deg, #2fa361, #135f38); transform: rotate(-.7deg); }
.sf-dash-money-card--due { background: linear-gradient(155deg, #e0447a, #98123f); transform: rotate(.7deg); }
.sf-dash-money-label { font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: rgba(255,255,255,.85); }
.sf-dash-money-value { font-size: 25px; font-weight: 800; line-height: 1.12; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.sf-dash-money-sub { font-size: 13px; color: rgba(255,255,255,.85); }
.sf-dash-money-sub strong { color: #fff; }
.sf-dash-money-go { display: inline-flex; align-items: center; gap: 5px; margin-top: auto; padding-top: 8px; font-size: 12px; font-weight: 800; color: #fff; }
.sf-dash-money-go img { display: block; flex: none; }

/* ---------- the activity split inside a money card ------------------------
   Three rows, one per class type, always all three and always in the same
   order so the column can be scanned rather than read. The collected card
   carries two amount columns (today, month); the dues card carries one.

   Small and secondary on purpose: the headline above stays the thing you see
   first. Amounts are right-aligned and tabular so they line up down the
   column, which is the whole point of putting them in one.

   The icons are the app's own finished activity tiles -- full-colour artwork on
   their own ground, so they carry the activity's colour without being recoloured
   and without having to survive the card's gradient behind them, which a tinted
   letter would not. */
.sf-dash-split {
  display: grid;
  grid-template-columns: 20px repeat(2, minmax(0, 1fr));
  align-items: center;
  gap: 2px 6px;
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px solid rgba(255,255,255,.28);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

/* The dues card splits one figure, not two. */
.sf-dash-split--one { grid-template-columns: 20px minmax(0, 1fr); }

/* Each row is its own grid row; the spans inside sit straight into the parent
   grid so the columns line up across every row. */
.sf-dash-split-head,
.sf-dash-split-row { display: contents; }

.sf-dash-split-head > span {
  font-size: 9.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: rgba(255,255,255,.62); text-align: right;
}

.sf-dash-split-row > span { text-align: right; color: rgba(255,255,255,.95); font-weight: 700; }

/* The left column: the icon, or a single letter when an activity has no tile. */
.sf-dash-split-act {
  display: flex; align-items: center; justify-content: flex-start;
  min-width: 0;
  font-weight: 800;
  color: rgba(255,255,255,.85);
}
.sf-dash-split-act img { display: block; width: 16px; height: 16px; border-radius: 4px; }

/* Money that belongs to no class type. Drawn only when there is any, and set
   apart so it reads as a gap in the data rather than a fourth class. */
.sf-dash-split-row--other > span { color: rgba(255,255,255,.72); font-style: italic; }

/* ---------- members ---------- */
.sf-dash-members { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.sf-dash-mtile {
  position: relative; min-width: 0; display: flex; flex-direction: column; justify-content: center;
  min-height: 88px; padding: 12px 36px 12px 14px; border-radius: 18px; color: #fff;
  border: 1px solid rgba(255,255,255,.32);
  box-shadow: 0 10px 20px -11px rgba(20,10,35,.6);
}
.sf-dash-mtile:active { transform: translateY(1px); }
.sf-dash-mtile-value { font-size: 33px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.sf-dash-mtile-label { margin-top: 4px; font-size: 12px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; }
.sf-dash-mtile .sf-dash-go { position: absolute; top: 12px; right: 12px; }
.sf-dash-mtile--good { background: linear-gradient(155deg, #3cae68, #1e7a44); }
.sf-dash-mtile--warn { background: linear-gradient(155deg, #f5a623, #dd7a00); color: #3c2500; }
.sf-dash-mtile--bad  { background: linear-gradient(155deg, #e85d5d, #b52c2c); }
.sf-dash-mtile--hold { background: var(--sf-dash-glass); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); color: #2b2a1f; }
.sf-dash-mtile--zero { opacity: .68; }

.sf-dash-absent {
  display: flex; align-items: center; gap: 12px; min-height: var(--sf-dash-tap);
  margin-top: 12px; padding: 12px 14px; border-radius: 16px;
  background: #ffd166; color: #4b3100;
  box-shadow: 0 10px 20px -12px rgba(20,10,35,.6);
}
.sf-dash-absent:active { filter: brightness(.97); }
.sf-dash-absent-text { flex: 1; font-size: 14px; font-weight: 600; }
.sf-dash-absent-text strong { font-weight: 800; }
.sf-dash-absent .sf-dash-ico { color: #4b3100; }

/* ---------- instructors ---------- */
.sf-dash-teach-row { display: flex; align-items: center; gap: 12px; min-height: var(--sf-dash-tap); padding: 8px 0; border-top: 1px solid var(--sf-dash-glass-line); }
.sf-dash-teach-row:first-of-type { border-top: 0; padding-top: 0; }
.sf-dash-teach-dot { width: 10px; height: 10px; flex: none; border-radius: 50%; background: #6fd695; }
.sf-dash-teach-row:nth-of-type(5n+2) .sf-dash-teach-dot { background: #ffb45e; }
.sf-dash-teach-row:nth-of-type(5n+3) .sf-dash-teach-dot { background: #ff5c9d; }
.sf-dash-teach-row:nth-of-type(5n+4) .sf-dash-teach-dot { background: #c5a4ff; }
.sf-dash-teach-name { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; text-transform: capitalize; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-dash-teach-count { font-size: 14px; color: var(--sf-dash-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sf-dash-teach-count strong { color: #2b2a1f; font-weight: 800; font-size: 16px; }

/* Cover only shows when there is cover, so it never takes a line for nothing. */
.sf-dash-teach-cover { font-size: 12px; font-weight: 700; color: var(--sf-dash-warn); white-space: nowrap; }

/* ---------- account actions + footer ---------- */

/* Change password sits beside Log out because the dashboards are the only
   screens in the app that link to it — dropping it here would leave no way to
   reach it at all. Both are full width and stacked: side by side, the longer
   label wrapped at 360px and read as two buttons. */
.sf-dash-account { display: flex; flex-direction: column; gap: 10px; }
.sf-dash-account form { margin: 0; }
.sf-dash-logout, .sf-dash-ghost {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  min-height: var(--sf-dash-tap); border: 1.5px solid var(--sf-dash-glass-edge); border-radius: 16px;
  background: var(--sf-dash-glass); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  color: #2b2a1f; font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
.sf-dash-logout:active, .sf-dash-ghost:active { filter: brightness(.94); }

/* Only the rainbow rule. The tagline and the credit under it come from the
   shared _SiteFooter partial, which the layout already renders on every page —
   repeating them here would print the studio's tagline twice on this screen. */
.sf-dash-foot { padding: 2px 2px 0; }

/* opacity is restated, not inherited. Bootstrap Reboot ships
   `hr { ...; opacity: .25 }`, and nothing else here touches opacity, so the
   wing gradient came out as a quarter-strength smudge. Everything else Reboot
   sets on an hr -- margin, border, colour -- is already overridden above it. */
.sf-dash-wingbar {
  height: 4px; border: 0; width: 132px; margin: 0 auto;
  border-radius: 999px; opacity: 1;
  background: var(--sf-dash-wing);
}

/* The design shipped a container query here that widened quick access to six
   columns and the member tiles to four once the container passed 480px:

     @container (min-width: 480px) {
       .sf-dash-tiles   { grid-template-columns: repeat(6, minmax(0,1fr)); }
       .sf-dash-members { grid-template-columns: repeat(4, minmax(0,1fr)); }
     }

   It is deleted rather than left commented in place, because it always fired
   here. .sf-content caps the column at 640px and pads it by 1rem, so .sf-dash
   measures 608px on any window at or past 640px -- comfortably over the 480px
   threshold. The result was the six quick-access tiles strung across a single
   row, and the four member tiles in one line, on every desktop browser.

   Quick access is meant to read as two rows of three -- Devices, Users, Plans,
   then Aerobics, Yoga, Dance -- and the member states as a 2x2 block, at every
   width. Both grids are now fixed at their phone shape and nothing widens them.

   With this gone nothing queries the container, so .sf-dash no longer declares
   container-type either -- see the note there. */
