:root{
  --navy:#11112D; --green:#166232; --blue:#2D317D; --deep:#082111;
  --bg:#0b0b1c; --card:#16162e; --card2:#1d1d3a; --line:#262649;
  --text:#eef0f6; --muted:#9aa0b8; --accent:#2f9e5c;
  --safe: env(safe-area-inset-bottom, 0px);
  /* Installed to the home screen, iOS runs this full-screen under a
     translucent status bar (apple-mobile-web-app-status-bar-style in
     index.html), so the top of the viewport is behind the clock and the
     battery. The bar pads itself by this much: the navy still reaches the
     very top of the screen, but the wordmark starts below the notch.
     Zero in a normal browser tab, where the browser owns that strip. */
  --safe-top: env(safe-area-inset-top, 0px);
  /* Dark is this app's native look, so it lives on bare :root. Light is defined
     twice below — once behind prefers-color-scheme for people who never open
     the setting, once behind [data-theme] for people who do — and each guard
     excludes the other so an explicit choice always beats the operating system.
     Every colour goes through a token: a literal that only reads on one ground
     is how an app ends up with dark text on a dark card. */
  --page:#07070f;
  --avbg:#23234a;
  --quote:#d6dae9;
  --about:#cdd2e2;
  --vid-a:#1c2f24; --vid-b:#131333; --vid-ic:#7fbf9a;
  --frame:#0b0b1c;
  --warn:#7a5a20;
  --star:#e0a72a;
  --onbrand:#fff;
  --navbg:rgba(17,17,45,.97);
  --appshadow:0 0 70px rgba(0,0,0,.7);
  /* Headline stack, kept identical to the Premiere Partner portal so the two
     surfaces read as one brand. "Copperplate" must come FIRST: that is the
     family name on macOS and iOS, where nearly every client opens this. The
     "Copperplate Gothic *" names are the Windows/Adobe ones and match nothing
     on an iPhone — with only those listed, Apple devices fell straight through
     to Optima, which is why the headings looked wrong on the phone. */
  --head: Copperplate, "Copperplate Gothic Bold", "Copperplate Gothic",
          "Big Caslon", "Palatino Linotype", Palatino, Georgia, serif;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{background:var(--page);color:var(--text);line-height:1.5;display:flex;justify-content:center;
  font-family:Calibri,"Segoe UI",system-ui,-apple-system,sans-serif}
h1,h2,h3,h4{font-family:var(--head);
  letter-spacing:.06em;text-transform:uppercase}
a{color:var(--accent)}

.app{width:100%;max-width:460px;min-height:100vh;background:var(--bg);display:flex;flex-direction:column;
  box-shadow:var(--appshadow);position:relative}
@media(min-width:520px){.app{border-left:1px solid var(--line);border-right:1px solid var(--line)}}

.topbar{position:sticky;top:0;z-index:20;background:var(--navy);border-bottom:2px solid var(--green);
  padding:calc(11px + var(--safe-top)) 14px 11px;display:flex;align-items:center;gap:9px;
  min-height:calc(50px + var(--safe-top));color:#fff}
/* The real TFC mark, the same file the Premiere Partner portal uses. It sits on
   the navy bar, and the artwork already carries its own navy ground, so it needs
   no plate behind it. */
.cube{width:30px;height:30px;flex:0 0 auto;display:block}
.cube img{width:100%;height:100%;object-fit:contain;display:block}
.wordmark{font-family:var(--head);font-size:11px;letter-spacing:.13em;flex:1;line-height:1.25}
.backbtn{background:none;border:0;color:#5fcf8f;font-size:16px;cursor:pointer;padding:0 4px 0 0;font-family:inherit}
.backbtn[hidden]{display:none}

main{flex:1 1 auto;padding:14px 14px 96px}
/* Auto columns, not a fixed four: a co-branded app carries a fifth tab for the
   partner, and a hard-coded repeat(4) squeezed it off the end of the bar. */
.nav{position:fixed;bottom:0;left:0;right:0;z-index:30;margin:0 auto;max-width:460px;
  background:var(--navbg);backdrop-filter:blur(10px);border-top:1px solid var(--line);
  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;padding:8px 0 calc(10px + var(--safe))}
.nav button{background:none;border:0;color:var(--muted);font-size:10px;cursor:pointer;padding:2px 2px;
  display:flex;flex-direction:column;align-items:center;gap:3px;font-family:inherit;min-width:0}
/* The fifth tab is labelled with a real first name, and names get long. At five
   tabs on a 390px screen each one has about 74px, so the label truncates rather
   than wrapping the bar into two rows. */
.nav button .lb{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav button .ic{font-size:17px;line-height:1}
.nav button.on{color:var(--accent)}

.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:14px;margin-bottom:11px}
.card.flush{padding:0;overflow:hidden}
.sect{font-size:10px;color:var(--muted);letter-spacing:.15em;text-transform:uppercase;margin:20px 0 9px;
  font-family:var(--head)}
.sect:first-child{margin-top:4px}

.hero{text-align:center;padding:18px 14px 14px}
.av{width:78px;height:78px;border-radius:50%;border:3px solid var(--accent);display:grid;place-items:center;
  margin:0 auto 10px;font-size:22px;background:var(--avbg);color:var(--text);overflow:hidden;
  font-family:var(--head)}
.av img{width:100%;height:100%;object-fit:cover}
.av.sm{width:50px;height:50px;font-size:14px;border-width:2px;margin-bottom:7px}
.av.blue{border-color:var(--blue)}
.hero h2{font-size:20px;margin-bottom:4px}
.hero .s{font-size:12px;color:var(--muted)}
.stars{color:var(--star);font-size:14px;margin-top:6px;letter-spacing:2px}
.socials{display:flex;justify-content:center;gap:15px;margin-top:12px;font-size:16px;opacity:.85}
.socials a{text-decoration:none;color:inherit;display:flex;align-items:center}
/* Sized in em so the existing font-size cascade still shrinks them: .socials.sm
   drops to 13px and the marks follow without a second rule. */
.socials svg{width:1em;height:1em;display:block}
.cob{display:grid;grid-template-columns:1fr auto 1fr;gap:9px;align-items:start;text-align:center}
.cob .amp{color:var(--muted);font-size:11px;padding-top:20px}
.cob h4{font-size:13.5px;margin-bottom:3px}
.cob .s{font-size:10px;color:var(--muted);line-height:1.35}
.pill{display:inline-block;font-size:9px;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);
  border:1px solid var(--line);background:var(--card2);padding:3px 9px;border-radius:99px}

.btn{background:var(--green);color:var(--onbrand);border:0;border-radius:10px;padding:13px;width:100%;font-size:14px;
  font-weight:600;cursor:pointer;font-family:inherit;display:block;text-align:center;text-decoration:none}
.btn.alt{background:var(--blue)}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--text);font-weight:400}
.btn.sm{padding:10px;font-size:13px}
.two{display:grid;grid-template-columns:1fr 1fr;gap:9px}

.row{display:flex;align-items:center;justify-content:space-between;gap:11px;padding:13px 14px;
  border-bottom:1px solid var(--line);cursor:pointer;text-decoration:none;color:inherit}
.row:last-child{border-bottom:0}
.row:active{background:var(--card2)}
.row .l{display:flex;align-items:center;gap:11px;font-size:14px;min-width:0}
/* The name of the thing is heavier than the line explaining it. A list of eight
   links set entirely in one weight reads as a wall; bolding the title alone is
   what lets the eye pick a row out without enlarging anything. The icon square
   and the sub-line opt back out below — both live inside the same title div. */
.row .l > div:not(.ic){font-weight:600}
.row .ic{width:30px;height:30px;border-radius:8px;background:var(--card2);display:grid;place-items:center;
  font-size:14px;flex:0 0 auto}
.row .sub{font-size:11px;color:var(--muted);line-height:1.3;font-weight:400}
.row .ar{color:var(--muted);font-size:16px;flex:0 0 auto}

.applycard{background:linear-gradient(140deg,var(--deep),var(--navy));border:1px solid var(--green)}
.applycard .lbl{font-size:11px;color:#9fd4b4;letter-spacing:.1em;text-transform:uppercase;margin-bottom:9px}

.vid{height:88px;border-radius:10px;background:linear-gradient(140deg,var(--vid-a),var(--vid-b));
  display:grid;place-items:center;font-size:22px;margin-bottom:8px;color:var(--vid-ic)}
.tile{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:11px;cursor:pointer;
  text-decoration:none;color:inherit;display:block}
.tile .t{font-size:12px;line-height:1.3;font-weight:600}
.tile .ic{font-size:20px;display:block;margin-bottom:6px}

.quote{font-size:13px;font-style:italic;color:var(--quote)}
.by{font-size:11px;color:var(--muted);margin-top:6px}

.calcwrap{margin:-14px -14px 0}
.calchead{padding:13px 14px 11px;border-bottom:1px solid var(--line)}
.calchead h2{font-size:14px;margin-bottom:2px}
.calchead p{font-size:11px;color:var(--muted)}
iframe.broki{width:100%;border:0;display:block;background:var(--frame);height:640px;transition:height .18s ease}
.loading{padding:40px 14px;text-align:center;color:var(--muted);font-size:13px}
.disc{font-size:10px;color:var(--muted);line-height:1.5;padding:12px 14px 0}
.warncard{border-color:var(--warn)}

footer{font-size:10px;color:var(--muted);line-height:1.6;text-align:center;padding:22px 6px 4px}
.note{font-size:11px;color:var(--muted);line-height:1.5}
code{background:var(--card2);padding:1px 5px;border-radius:4px;font-size:11px}

/* Install lives in the page, at the bottom of Home — not in a floating bar that
   covered content and could be dismissed forever. It is one of the few things
   we actually want every client to do, so it should still be there tomorrow. */
.installcard{background:var(--card2);border:1px solid var(--accent);border-radius:14px;
  padding:14px;margin-bottom:11px;text-align:center}
.installcard .t{font-size:13px;font-weight:600;margin-bottom:4px}
.installcard .note{margin-bottom:11px}
/* Numbered steps, left-aligned inside a centred card: a three-step
   instruction read centred is genuinely harder to follow, because the eye
   loses the left edge between steps. */
.steps{text-align:left;margin:0 0 11px;padding:0;list-style:none;counter-reset:step}
.steps li{position:relative;padding:0 0 0 26px;margin-bottom:7px;font-size:12px;line-height:1.5;
  color:var(--quote);counter-increment:step}
.steps li:last-child{margin-bottom:0}
.steps li::before{content:counter(step);position:absolute;left:0;top:1px;width:18px;height:18px;
  border-radius:50%;background:var(--accent);color:var(--onbrand);font-size:10px;font-weight:700;
  display:grid;place-items:center;line-height:1}
.steps .k{color:var(--text);font-weight:600}
.installcard .why{font-size:10.5px;color:var(--muted);line-height:1.5;margin-top:10px}

/* A review is a quote with a name, a date and a star line. Whole reviews, in
   full — a review trimmed to its best sentence is not the client's review
   any more, and Google shows the same words to anyone who looks. */
.rev{padding:14px;border-bottom:1px solid var(--line)}
.rev:last-child{border-bottom:0}
.rev .h{display:flex;align-items:baseline;justify-content:space-between;gap:9px;margin-bottom:5px}
.rev .who{font-size:13px;font-weight:600}
.rev .when{font-size:10.5px;color:var(--muted);flex:0 0 auto}
.rev .stars{margin:0 0 7px;font-size:12px}
.rev .quote{font-style:normal;font-size:13px;color:var(--quote);white-space:pre-wrap}
/* Google requires its reviews be shown as Google reviews. One line under the
   list says where they came from and links to the profile they live on. */
.revsrc{font-size:10.5px;color:var(--muted);text-align:center;padding:12px 6px 0;line-height:1.5}

/* A Learn row may carry a real logo instead of an emoji — the podcast is its own
   brand, not a category. Fills the same 30px square the emoji sits in. */
.row .ic.img{padding:0;overflow:hidden;background:#000}
.row .ic.img img{width:100%;height:100%;object-fit:cover;display:block}

/* ---- light theme ---------------------------------------------------------
   Not an inversion: the topbar keeps its navy and green so the brand does not
   change with a display setting, and the accent darkens so it reads against
   white instead of glowing on it.

   Defined twice on purpose. The media query serves everyone who never opens the
   setting; the [data-theme] rule serves everyone who does. Each guard excludes
   the other case so an explicit choice always beats the operating system. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
  --bg:#f4f6fb; --card:#ffffff; --card2:#eef1f8; --line:#dde1ee;
  --text:#14162b; --muted:#5c6280; --accent:#166232;
  --page:#e7eaf3;
  --avbg:#e4e8f4;
  --quote:#2a2e46;
  --about:#3a3f57;
  --vid-a:#e8f0ea; --vid-b:#e6e8f4; --vid-ic:#2f7a52;
  --frame:#ffffff;
  --warn:#b98a2c;
  --star:#c98a12;
  --navbg:rgba(255,255,255,.97);
  --amberbg:#fdf3e3;--ambertx:#7a5010;--amberln:#f0e0c0;
  --appshadow:0 0 60px rgba(20,25,60,.14);
  }
}
:root[data-theme="light"] {
  --bg:#f4f6fb; --card:#ffffff; --card2:#eef1f8; --line:#dde1ee;
  --text:#14162b; --muted:#5c6280; --accent:#166232;
  --page:#e7eaf3;
  --avbg:#e4e8f4;
  --quote:#2a2e46;
  --about:#3a3f57;
  --vid-a:#e8f0ea; --vid-b:#e6e8f4; --vid-ic:#2f7a52;
  --frame:#ffffff;
  --warn:#b98a2c;
  --star:#c98a12;
  --navbg:rgba(255,255,255,.97);
  --amberbg:#fdf3e3;--ambertx:#7a5010;--amberln:#f0e0c0;
  --appshadow:0 0 60px rgba(20,25,60,.14);
}

/* The About paragraph was an inline colour that only worked on a dark ground. */
.about{font-size:13px;color:var(--about)}

/* Co-brand socials sit under each person, so they are smaller and tighter than
   the solo hero's row — and each half gets the same set, which is the point. */
.socials.sm{gap:11px;margin-top:7px;font-size:13px}

/* Appearance control. A segmented three-way rather than a switch, because
   "System" is a real third choice and a two-state toggle cannot express it. */
.themecard{background:var(--card);border:1px solid var(--line);border-radius:14px;
  padding:14px;margin-bottom:11px}
.themecard .t{font-size:13px;font-weight:600;margin-bottom:3px}
.seg{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:11px;
  background:var(--card2);border:1px solid var(--line);border-radius:11px;padding:4px}
.seg button{background:none;border:0;border-radius:8px;padding:9px 4px;cursor:pointer;
  color:var(--muted);font-family:inherit;font-size:12.5px;display:flex;align-items:center;
  justify-content:center;gap:6px}
.seg button.on{background:var(--card);color:var(--text);font-weight:600;
  box-shadow:0 1px 3px rgba(0,0,0,.18)}
.seg button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}

/* The apply card keeps its dark gradient in both themes — it is the one
   deliberately heavy block on the page, and it should not become a pale panel
   in light mode. Everything inside it therefore takes fixed light colours: page
   tokens would flip out from under it and put dark text on a near-black ground,
   which is exactly what happened the first time light mode was rendered. */
.applycard .note{color:#b9c2d6}

/* ---------- the partner's own content ------------------------------------
   A launcher on Home for whatever the partner has posted, plus the calculators.
   Buttons only exist for kinds that have something behind them: a tile that
   opens an empty list has already cost the client a tap. */
.lnch{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:4px}
.lnchr{display:flex;flex-direction:column;align-items:flex-start;gap:5px;
  background:var(--card);border:1px solid var(--line);border-radius:14px;padding:13px 13px 12px;
  font-family:inherit;color:var(--text);cursor:pointer;text-align:left;min-height:86px;
  justify-content:space-between;position:relative}
.lnchr:active{background:var(--card2)}
.lnchr .ic{font-size:19px;line-height:1}
.lnchr .t{font-size:13px;font-weight:600;line-height:1.25}
/* The count is the point of the tile — it says there is something in there. */
.lnchr .n{position:absolute;top:11px;right:12px;font-size:10px;font-weight:700;
  color:var(--accent);background:var(--card2);border:1px solid var(--line);
  border-radius:20px;padding:2px 8px;min-width:22px;text-align:center}
/* The calculators tile spans the row when it is the only one, and reads as the
   app's own rather than the partner's. */
.lnchr.calc{border-color:var(--green);grid-column:1/-1}
.lnchr.calc .n{color:var(--accent)}

.partnercard{display:flex;align-items:center;gap:14px;text-align:left}
.partnercard .av{margin:0;flex:0 0 auto}
.partnercard .pw{min-width:0}
.partnercard .nm{font-family:var(--head);font-size:16px;letter-spacing:.02em;line-height:1.2}
.partnercard .fm{font-size:12px;color:var(--muted);margin-top:3px}
.partnercard .ti{font-size:11px;color:var(--muted);opacity:.8}
.socials.mt{justify-content:flex-start;margin-top:13px}
.note.tiny{font-size:10.5px;text-align:center;margin:14px 4px 0;opacity:.85}

/* ---------- their brokerage's chrome (co-branded apps only) ----------------
   The bar hands the top of the screen to the partner. Its colours come from the
   feed and are set inline in paintChrome(), so nothing here hard-codes one
   brokerage's palette.

   The accent reaches exactly two more things — the active tab and the partner's
   photo ring — and stops. Buttons stay TFC green, the Apply CTA especially: a
   realtor is not licensed for mortgages, and mortgage buttons wearing the
   brokerage's colours start to read as though they were. */
.topbar[data-brok]{border-bottom-width:3px}
/* Their mark sits on a white plate. Brokerage artwork is drawn for light
   grounds — RE/MAX's own SVG carries #000e35, the same navy as their bar, so
   half of it would disappear into the background. */
.topbar[data-brok] .cube{background:none;border:0;padding:0;width:auto;height:auto}
.plate{background:#fff;border-radius:6px;padding:4px 6px;display:flex;align-items:center;
  flex:0 0 auto}
.plate img{height:15px;display:block}
.topbar[data-brok] .wordmark{line-height:1.2}
.wordmark .bnm{display:block;font-family:var(--head);font-size:11px;letter-spacing:.09em}
.wordmark small{display:block;font-size:8.5px;letter-spacing:.05em;opacity:.72;
  font-family:var(--head);margin-top:2px}
.nav button.on{color:var(--brok,var(--accent))}
.partnercard .av,.cob .av.blue,.hero .av.blue{border-color:var(--brok,var(--blue))}

/* Stephen, on a screen whose bar is no longer his. A labelled block rather than
   a line of fine print: with no TFC bar this is the identification the rules
   actually turn on. */
.attrib{border-left:3px solid var(--green)}
.attrib .lb{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
  margin-bottom:8px}
.attrib .who{display:flex;align-items:center;gap:11px}
.attrib .tfcmini{width:30px;height:30px;object-fit:contain;flex:0 0 auto;border-radius:7px}
.attrib .nm{font-family:var(--head);font-size:12.5px;letter-spacing:.03em}
.attrib .ro{font-size:11.5px;color:var(--muted);margin-top:2px}
.attrib .lic{font-size:10.5px;color:var(--muted);opacity:.85;margin-top:3px;line-height:1.4}

/* The tester, saying so. Amber rather than red: this is a note about what you
   are looking at, not a fault. Mirrors the strip the partner page already
   carries so the two surfaces admit it the same way. */
.demostrip{background:var(--amberbg,#3a2f10);color:var(--ambertx,#f0d9a0);
  border:1px solid var(--amberln,#5c4a1c);border-radius:10px;padding:8px 11px;
  font-size:10.5px;letter-spacing:.05em;text-align:center;margin-bottom:12px}

/* The two home tools above the calculators. A green edge is the only thing
   separating them from the calculator card below — they are the app's own, not
   a partner's, and the border says so without a second heading style. */
.hometools{border-color:var(--green)}

/* ---------- the contact card ----------------------------------------------
   The QR is the one element on this app that ignores the theme. A code drawn
   light-on-dark is a code that a good half of the camera apps in the world
   will not read, so it keeps its white plate in dark mode and the plate keeps
   a quiet margin of its own — the four-module quiet zone is inside the SVG,
   and this padding is what stops a dark card crowding it on screen. */
.qrcard{padding:16px 14px 14px;text-align:center}
.qrplate{background:#fff;border-radius:12px;padding:10px;display:block;
  max-width:320px;margin:0 auto}
.qrplate svg{width:100%;height:auto;display:block}
.qrwho{margin-top:13px;line-height:1.35}
.qrwho strong{display:block;font-size:14px;font-weight:600}
.qrwho span{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.qrhint{margin-top:10px;text-align:center}

/* What the card contains, spelled out rather than promised. Two columns on a
   390px screen leaves the values room to wrap, which several of them need —
   an email address and a LinkedIn URL are both longer than half a phone. */
.contactlist .crow{display:grid;grid-template-columns:82px 1fr;gap:11px;
  padding:11px 14px;border-bottom:1px solid var(--line);align-items:baseline}
.contactlist .crow:last-child{border-bottom:0}
.contactlist .k{font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);line-height:1.4}
.contactlist .v{font-size:12.5px;line-height:1.45;word-break:break-word;overflow-wrap:anywhere}
