/* Ikonotechnics theme for Element Web.
 *
 * The palette is not invented. It is the one already declared in
 * ikonotechnics-site's own CSS custom properties, copied across so the chat
 * client and the site are the same object:
 *
 *   --void  #0B0B0E   --char  #15151B   --line  #2A2A33
 *   --ash   #6B6557   --bone  #F2E8D5   --ember #F7A821
 *   --alert #E5484D   plus the magenta #D63A8E and cyan #3AD6E0 accents
 *
 * config.json carries the colours it can. Element's custom-theme block writes
 * `--<key>` custom properties and can do nothing else, so fonts, the Compound
 * design tokens that Element 1.12 actually renders from, and anything
 * structural have to live here. build.sh links this from index.html.
 *
 * Compound is the current system: the stylesheet reads --cpd-color-* about a
 * thousand times per token, and the legacy names in config.json only reach the
 * older screens. Setting both is why the app looks themed rather than
 * half-themed.
 */

@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

:root,
body,
.cpd-theme-dark,
.cpd-theme-light {
  --ikono-void: #0b0b0e;
  --ikono-char: #15151b;
  --ikono-line: #2a2a33;
  --ikono-ash: #6b6557;
  --ikono-bone: #f2e8d5;
  --ikono-magenta: #d63a8e;
  --ikono-cyan: #3ad6e0;
  --ikono-ember: #f7a821;
  --ikono-alert: #e5484d;

  /* Type. The site is monospace throughout and the client should not be the
   * one surface that is not. Element renders body copy from the sans token, so
   * that is the one to move; the mono token is already mono. */
  --cpd-font-family-sans: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --cpd-font-family-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Surfaces */
  --cpd-color-bg-canvas-default: var(--ikono-void);
  --cpd-color-bg-canvas-disabled: var(--ikono-char);
  --cpd-color-bg-subtle-primary: var(--ikono-line);
  --cpd-color-bg-subtle-secondary: var(--ikono-char);
  --cpd-color-bg-action-primary-rest: var(--ikono-magenta);
  --cpd-color-bg-action-primary-hovered: #e250a0;
  --cpd-color-bg-action-primary-pressed: #c02f7e;

  /* Text */
  --cpd-color-text-primary: var(--ikono-bone);
  --cpd-color-text-secondary: var(--ikono-ash);
  --cpd-color-text-action-accent: var(--ikono-magenta);
  --cpd-color-text-critical-primary: var(--ikono-alert);
  --cpd-color-text-on-solid-primary: var(--ikono-void);

  /* Lines and icons */
  --cpd-color-border-interactive-primary: var(--ikono-line);
  --cpd-color-border-interactive-secondary: var(--ikono-line);
  --cpd-color-icon-primary: var(--ikono-bone);
  --cpd-color-icon-secondary: var(--ikono-ash);
  --cpd-color-icon-tertiary: var(--ikono-ash);
  --cpd-color-icon-accent-tertiary: var(--ikono-magenta);

  /* Element still reads the greys directly in a few hundred places. Left
   * roughly neutral so nothing turns muddy, but pulled to the void's hue. */
  --cpd-color-gray-100: #101015;
  --cpd-color-gray-200: var(--ikono-char);
  --cpd-color-gray-300: #1e1e26;
  --cpd-color-gray-400: var(--ikono-line);
  --cpd-color-gray-600: #4a4a55;
  --cpd-color-gray-800: var(--ikono-ash);
  --cpd-color-gray-1400: var(--ikono-bone);
}

/* Element injects its own styles.css at runtime, AFTER any stylesheet linked
 * in the document head, so plain component selectors here lose the cascade.
 * Observed: .mx_AuthPage computed to transparent with this file loaded and
 * parsed. Custom properties above are unaffected because they are declared on
 * :root and inherit; only these component rules need the extra weight, so
 * every selector below is prefixed with body to outrank Element's own.
 */

/* The cyan is the second voice and it is used sparingly, the way the site uses
 * it: for the thing you are meant to notice, not for decoration. */
body .mx_RoomTile_selected,
body .mx_RoomSublist_headerContainer:hover {
  border-left: 2px solid var(--ikono-cyan);
}

/* Login and registration. The eye sits on near-black, so give it room and stop
 * Element's default card from washing it out. */
/* !important on these two only. Element ships a background image on the auth
 * page from its own stylesheet and wins the cascade whatever selector weight is
 * used here, because styles.css is injected after this file. Observed: the
 * border below applied and the background did not. Everywhere else the extra
 * body prefix is enough. */
body .mx_AuthPage {
  background-color: var(--ikono-void) !important;
  background-image:
    radial-gradient(ellipse at 50% 0%, rgba(214, 58, 142, 0.10), transparent 60%),
    radial-gradient(ellipse at 50% 100%, rgba(58, 214, 224, 0.06), transparent 55%) !important;
}
body .mx_AuthPage_modal {
  background-color: var(--ikono-char) !important;
  border: 1px solid var(--ikono-line);
  border-radius: 4px;
}
/* Element dresses the sign-in card with a blurred stock photograph of a lake
 * behind a 59 percent WHITE overlay. On a near-black theme that reads as a
 * bright panel stuck to the side of the card, and no amount of token setting
 * touches it because it is an image plus an alpha fill on two inner elements.
 * Found by taking a screenshot and looking; every computed colour I had checked
 * up to that point was already correct. */
body .mx_AuthPage_modalBlur {
  background-image: none !important;
  background-color: var(--ikono-char) !important;
}
body .mx_AuthPage_modalContent {
  background-color: rgba(21, 21, 27, 0.72) !important;
}

/* The lockup is set vertically and wants the whole panel, not a logo slot.
 * Element's default caps the mark at a logo's height and centres it near the
 * top, which leaves a tall narrow column mostly empty with a small mark in it. */
body .mx_AuthHeaderLogo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
}
body .mx_AuthHeaderLogo img,
body .mx_AuthHeaderLogo svg {
  max-height: 100%;
  height: 380px;
  width: auto;
}
body .mx_AuthHeader {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-block: 24px;
}
/* Element's auth footer is Blog, Mastodon, GitHub and Powered by Matrix, none of
 * which is ours. On a private table it is four ways off the site on the one
 * screen where the only wanted action is signing in. */
body .mx_AuthFooter {
  display: none;
}

/* The welcome screen gets the eye, not the lockup. Element hands the same
 * branding.auth_header_logo_url to two slots with opposite proportions: the
 * sign-in side rail, which is tall and narrow and is what the rotated lockup was
 * drawn for, and this one, which caps by height. The lockup is 190x420, so at
 * the 48px this slot allows it came out 22px wide, an unreadable sliver. The eye
 * is square at 240x240 and is the mark that fits a logo slot.
 * The image is replaced rather than swapped, because src comes from config and
 * CSS cannot reach it. */
/* branding.auth_header_logo_url is handed to three slots, and the rotated lockup
 * only suits the first of them:
 *   .mx_AuthHeaderLogo          the sign-in side rail, tall and narrow
 *   .mx_DefaultWelcome_logo     the welcome card, logged out
 *   .mx_HomePage_default        the home page, logged in
 * The last two cap by height, so a 190x420 mark lands 22px wide. Both get the
 * eye instead, at the same size, so the two screens read as one system.
 *
 * The mark is drawn on the container and the original image removed, rather
 * than restyled. On the welcome card Element wraps the logo in
 * <a href="https://element.io" target="_blank">; restyling it would leave a link
 * off the site under our own mark, still clickable and still reachable by
 * keyboard. Taking the anchor out of the layout takes the link with it. The home
 * page has no anchor, but it is the same shape of fix and shares the rule. */
body .mx_Welcome .mx_DefaultWelcome_logo,
body .mx_HomePage_default .mx_HomePage_default_wrapper > img {
  display: none;
}
body .mx_Welcome .mx_DefaultWelcome::before,
body .mx_HomePage_default .mx_HomePage_default_wrapper::before {
  content: "";
  display: block;
  width: 76px;
  height: 76px;
  margin: 0 auto 8px;
  background: url("../art/eye-ember.svg") center / contain no-repeat;
}

/* The screen at #/welcome is a different component from the sign-in card, and
 * Element 1.12.24 carries a stale selector into it. UIFeature.registration is
 * being honoured: the wrapper really does get mx_WelcomePage_registrationDisabled.
 * But the rule that acts on that class hides .mx_DefaultWelcome_buttons_register,
 * which the refactored component no longer emits; the link is now an anchor with
 * a hashed Compound class. So Element disables registration and still shows the
 * button, on the one screen a player actually lands on first.
 * Matched by destination here, because a href cannot go stale the way a
 * generated class name can. */
body .mx_WelcomePage_registrationDisabled .mx_DefaultWelcome_buttons a[href="#/register"] {
  display: none;
}

/* Code and quoted material. This is a monospace house, so inline code needs a
 * different signal from the body text, which is no longer a contrast of face. */
body .mx_EventTile_body code,
body .mx_EventTile_body pre {
  background-color: var(--ikono-char);
  border: 1px solid var(--ikono-line);
  border-radius: 3px;
  color: var(--ikono-ember);
}

/* Scrollbars, because a dark app with light scrollbars reads as unfinished. */
* {
  scrollbar-color: var(--ikono-line) transparent;
  scrollbar-width: thin;
}
