tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

_feature-callout.scss (29039B)


      1 // This Source Code Form is subject to the terms of the Mozilla Public
      2 // License, v. 2.0. If a copy of the MPL was not distributed with this
      3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 @import 'feature-callout-theme';
      6 
      7 /* stylelint-disable max-nesting-depth */
      8 
      9 #feature-callout {
     10  // See _feature-callout-theme.scss for the theme mixins and
     11  // FeatureCallout.sys.mjs for the color values
     12  @include light-theme;
     13 
     14  position: absolute;
     15  z-index: 2147483647;
     16  outline: none;
     17  color: var(--fc-color);
     18  accent-color: var(--fc-accent-color);
     19  // Make sure HTML content uses non-native theming, even in chrome windows.
     20  -moz-theme: non-native;
     21  -moz-window-shadow: none;
     22 
     23  @media (prefers-color-scheme: dark) {
     24    @include dark-theme;
     25  }
     26 
     27  @at-root :root[lwt-popup='light'] #{&}:not(.simulateContent) {
     28    color-scheme: light;
     29 
     30    @include light-theme;
     31  }
     32 
     33  @at-root :root[lwt-popup='dark'] #{&}:not(.simulateContent) {
     34    color-scheme: dark;
     35 
     36    @include dark-theme;
     37  }
     38 
     39  @media (prefers-contrast) {
     40    @include hcm-theme;
     41  }
     42 
     43  // Account for feature callouts that may be rendered in the chrome but
     44  // displayed on top of content. Each context has its own color scheme, so they
     45  // may not match. In that case, we use the special media query below.
     46  &.simulateContent {
     47    color-scheme: env(-moz-content-preferred-color-scheme);
     48 
     49    // TODO - replace 2 mixins with a single mixin with light-dark() values.
     50    @media (-moz-content-prefers-color-scheme: light) {
     51      @include light-theme;
     52    }
     53 
     54    @media (-moz-content-prefers-color-scheme: dark) {
     55      @include dark-theme;
     56    }
     57 
     58    @at-root :root[lwt-newtab-brighttext] #{&}.lwtNewtab {
     59      color-scheme: dark;
     60 
     61      @include dark-theme;
     62    }
     63 
     64    @media (prefers-contrast) {
     65      @include hcm-theme;
     66    }
     67  }
     68 
     69  // The desired width of the arrow (the triangle base).
     70  --arrow-width: 33.9411px;
     71  // The width/height of the square that, rotated 90deg, will become the arrow.
     72  --arrow-square-size: calc(var(--arrow-width) / sqrt(2));
     73  // After rotating, the width is no longer the square width. It's now equal to
     74  // the diagonal from corner to corner, i.e. √2 * the square width. We need to
     75  // account for this extra width in some calculations.
     76  --extra-width-from-rotation: calc(var(--arrow-width) - var(--arrow-square-size));
     77  // The height of the arrow, once rotated and cut in half.
     78  --arrow-visible-height: calc(var(--arrow-width) / 2);
     79  // Half the width/height of the square. Calculations on the arrow itself need
     80  // to treat the arrow as a square, since they are operating on the element
     81  // _before_ it is rotated. Calculations on other elements (like the panel
     82  // margin that needs to make space for the arrow) should use the visible
     83  // height that treats it as a triangle.
     84  --arrow-visible-size: calc(var(--arrow-square-size) / 2);
     85  --arrow-center-inset: calc(50% - var(--arrow-visible-size));
     86  // Move the arrow 1.5px closer to the callout to account for subpixel rounding
     87  // differences, which might cause the corners of the arrow (which is actually
     88  // a rotated square) to be visible.
     89  --arrow-offset: calc(1.5px - var(--arrow-visible-size));
     90  // For positions like top-end, the arrow is 12px away from the corner.
     91  --arrow-corner-distance: 12px;
     92  --arrow-corner-inset: calc(var(--arrow-corner-distance) + (var(--extra-width-from-rotation) / 2));
     93  --arrow-overlap-magnitude: 5px;
     94  // Default min-height for feature callout ctas
     95  --button-min-height: 24px;
     96 
     97  @at-root panel#{&} {
     98    --panel-color: var(--fc-color);
     99    --panel-shadow: none;
    100    // Extra space around the panel for the shadow to be drawn in. The panel
    101    // content can't overflow the XUL popup frame, so the frame must be extended.
    102    --panel-shadow-margin: 6px;
    103    // The panel needs more extra space on the side that the arrow is on, since
    104    // the arrow is absolute positioned. This adds the visible height of the
    105    // arrow to the margin and subtracts 1 since the arrow is inset by 1.5px
    106    // (see --arrow-offset).
    107    --panel-arrow-space: calc(var(--panel-shadow-margin) + var(--arrow-visible-height) - 1.5px);
    108    // The callout starts with its edge aligned with the edge of the anchor. But
    109    // we want the arrow to align to the anchor, not the callout edge. So we need
    110    // to offset the callout by the arrow size and margin, as well as the margin
    111    // of the entire callout (it has margins on all sides to make room for the
    112    // shadow when displayed in a panel, which would normally cut off the shadow).
    113    --panel-margin-offset: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-corner-distance) + (var(--arrow-width) / 2)));
    114  }
    115 
    116  @at-root panel#{&}::part(content) {
    117    width: initial;
    118    border: 0;
    119    border-radius: 0;
    120    padding: 0;
    121    margin: var(--panel-shadow-margin);
    122    background: none;
    123    color: inherit;
    124    // stylelint-disable-next-line declaration-no-important
    125    overflow: visible !important;
    126  }
    127 
    128  @at-root div#{&} {
    129    transition: opacity 0.5s ease;
    130 
    131    &.hidden {
    132      opacity: 0;
    133      pointer-events: none;
    134    }
    135  }
    136 
    137  .onboardingContainer,
    138  .onboardingContainer .outer-wrapper {
    139    // Override the element transitions from aboutwelcome.scss
    140    --transition: none;
    141 
    142    // auto height to allow for arrow positioning based on height
    143    height: auto;
    144 
    145    // use a different approach to flipping to avoid the fuzzy aliasing that
    146    // transform causes.
    147    transform: none;
    148  }
    149 
    150  .screen {
    151    // override the RTL transform in about:welcome
    152    &:dir(rtl) {
    153      transform: none;
    154    }
    155 
    156    &[pos='callout'] {
    157      height: fit-content;
    158      min-height: unset;
    159      overflow: visible;
    160 
    161      &[layout='inline'] {
    162        .section-main {
    163          .main-content,
    164          .main-content.no-steps {
    165            width: 18em;
    166            padding-inline: 16px;
    167            padding-block: 0;
    168 
    169            .welcome-text {
    170              // Same height as the dismiss button
    171              height: 24px;
    172              margin-block: 12px;
    173              margin-inline: 0;
    174              padding: 0;
    175              white-space: nowrap;
    176            }
    177          }
    178 
    179          .dismiss-button {
    180            height: 24px;
    181            width: 24px;
    182            min-height: 24px;
    183            min-width: 24px;
    184            margin: 0;
    185            top: calc(50% - 12px);
    186            inset-inline-end: 12px;
    187          }
    188        }
    189      }
    190 
    191      .logo-container {
    192        display: flex;
    193        justify-content: center;
    194 
    195        .brand-logo {
    196          margin: 0;
    197 
    198          // This may not work for all future messages, so we may want to make
    199          // flipping the logo image in RTL mode configurable
    200          &:dir(rtl) {
    201            transform: rotateY(180deg);
    202          }
    203        }
    204      }
    205 
    206      .welcome-text {
    207        align-items: start;
    208        text-align: start;
    209        margin: 0;
    210        padding: 0;
    211        gap: 8px;
    212 
    213        h1,
    214        h2 {
    215          font-size: 0.813em;
    216          margin: 0;
    217          color: inherit;
    218        }
    219 
    220        h1 {
    221          font-weight: var(--heading-font-weight);
    222        }
    223 
    224        .inline-icon-container {
    225          display: flex;
    226          flex-flow: row wrap;
    227          align-items: center;
    228 
    229          .logo-container {
    230            height: 16px;
    231            width: 16px;
    232            margin-inline-end: 6px;
    233            box-sizing: border-box;
    234            -moz-context-properties: fill;
    235            fill: currentColor;
    236 
    237            img {
    238              height: 16px;
    239              width: 16px;
    240              margin: 0;
    241            }
    242          }
    243 
    244          &[alignment='top'],
    245          &[alignment='bottom'] {
    246            flex-wrap: nowrap;
    247 
    248            .logo-container {
    249              height: 1.5em; // match the title's line-height
    250              align-items: center;
    251              padding-bottom: 0.15em;
    252              box-sizing: border-box;
    253            }
    254          }
    255 
    256          &[alignment='top'] {
    257            align-items: start;
    258          }
    259 
    260          &[alignment='bottom'] {
    261            align-items: end;
    262          }
    263        }
    264 
    265      }
    266 
    267      #content-tiles-container {
    268        display: flex;
    269        flex-direction: column;
    270        margin: 0;
    271 
    272        .content-tile {
    273          .content-title-container {
    274            margin-block: inherit;
    275          }
    276 
    277          .multi-select-container {
    278            padding: 12px 0 0;
    279          }
    280        }
    281 
    282        .content-tile:not(:last-child) {
    283          margin-block: 0 20px;
    284        }
    285 
    286        .tile-title {
    287          font-size: 0.813em;;
    288        }
    289 
    290        .tile-title-container {
    291          margin-block: initial;
    292        }
    293      }
    294 
    295      .multi-select-container {
    296        margin: 0;
    297        font-size: 0.813em;
    298        row-gap: 12px;
    299        color: inherit;
    300        overflow: visible;
    301 
    302        #multi-stage-multi-select-label {
    303          font-size: inherit;
    304          // There's a 12px gap that pushes the .multi-select-container down
    305          // away from the .welcome-text. And there's an 8px gap between the h1
    306          // and h2 in the .welcome-text container. So subtract 4px to get the
    307          // desired 8px margin, so spacing is the same as for `subtitle`.
    308          margin: -4px 0 0;
    309          color: inherit;
    310        }
    311      }
    312 
    313      .cta-link {
    314        background: none;
    315        text-decoration: underline;
    316        cursor: pointer;
    317        border: none;
    318        padding: 0;
    319        color: var(--fc-link-color);
    320        order: -1;
    321        margin-inline-end: auto;
    322        margin-block: 8px;
    323 
    324        &:hover {
    325          color: var(--fc-link-color-hover);
    326        }
    327 
    328        &:active {
    329          color: var(--fc-link-color-active);
    330        }
    331      }
    332 
    333      // Secondary section is not included in callouts
    334      .section-secondary {
    335        display: none;
    336      }
    337 
    338      .section-main {
    339        height: fit-content;
    340        width: fit-content;
    341 
    342        .main-content {
    343          position: relative;
    344          overflow: hidden;
    345          border: 1px solid var(--fc-border);
    346          box-shadow: 0 2px 5px rgba(0, 0, 0, 15%);
    347          border-radius: 4px;
    348          padding: var(--callout-padding, 16px);
    349          width: 25em;
    350          gap: 16px;
    351          background: var(--fc-background);
    352 
    353          .main-content-inner {
    354            gap: 12px;
    355 
    356            .legal-paragraph {
    357              .text-link {
    358                color: var(--fc-color);
    359              }
    360            }
    361          }
    362 
    363          .steps {
    364            height: auto;
    365            position: absolute;
    366            // 16px is the callout's default bottom padding. The CTAs are 24px
    367            // tall by default, and the steps are 8px tall. So we need to offset
    368            // the steps by half the difference in order to center them.
    369            bottom: calc(var(--callout-padding, 16px) + (var(--cta-height, 24px) / 2) - 4px);
    370            padding-block: 0;
    371 
    372            .indicator {
    373              // using border will show up in Windows High Contrast Mode to improve accessibility.
    374              border: 4px solid var(--fc-step-color);
    375 
    376              &.current {
    377                border-color: var(--fc-accent-color);
    378              }
    379            }
    380 
    381            &:not(.progress-bar) {
    382              flex-flow: row nowrap;
    383              gap: 8px;
    384 
    385              .indicator {
    386                margin: 0;
    387              }
    388            }
    389 
    390            & .indicator.current,
    391            &.progress-bar .indicator.complete {
    392              border-color: var(--fc-accent-color);
    393            }
    394          }
    395        }
    396 
    397        .dismiss-button {
    398          font-size: 1em;
    399          inset-block: 0 auto;
    400          inset-inline: auto 0;
    401          margin-block: 16px 0;
    402          margin-inline: 0 16px;
    403          background-color: transparent;
    404 
    405          &[button-size='small'] {
    406            height: 24px;
    407            width: 24px;
    408            min-height: 24px;
    409            min-width: 24px;
    410          }
    411 
    412          &.with-background {
    413            background: url('chrome://global/skin/icons/close.svg') no-repeat center / 16px, var(--fc-dismiss-button-background);
    414 
    415            &:hover {
    416              background: url('chrome://global/skin/icons/close.svg') no-repeat center / 16px, var(--fc-dismiss-button-background-hover);
    417              color: var(--fc-button-color-hover);
    418 
    419              &:active {
    420                background: url('chrome://global/skin/icons/close.svg') no-repeat center / 16px, var(--fc-dismiss-button-background-active);
    421              }
    422            }
    423 
    424            @media (prefers-contrast) {
    425              background-color: var(--fc-button-background);
    426              border: 1px solid var(--fc-button-border);
    427              color: var(--fc-button-color);
    428 
    429              &:hover:not(:disabled),
    430              &[open] {
    431                background-color: var(--fc-button-background-hover);
    432                color: var(--fc-button-color-hover);
    433                border: 1px solid var(--fc-button-border-hover);
    434 
    435                &:active {
    436                  background-color: var(--fc-button-background-active);
    437                  color: var(--fc-button-color-active);
    438                  border: 1px solid var(--fc-button-border-active);
    439                }
    440              }
    441            }
    442          }
    443        }
    444      }
    445 
    446      .action-buttons {
    447        display: flex;
    448        flex-flow: row nowrap;
    449        align-items: stretch;
    450        justify-content: end;
    451        gap: 10px;
    452        // The Figma spec wants a 16px gap between major content blocks and the
    453        // action buttons. But the action buttons are siblings with the minor
    454        // content blocks, which want a 12px gap. So we use a 12px gap and just
    455        // add 4px of margin to the action buttons.
    456        margin-top: 4px;
    457 
    458        &[alignment='start'] {
    459          justify-content: start;
    460        }
    461 
    462        &[alignment='space-between'] {
    463          justify-content: space-between;
    464        }
    465 
    466        .secondary-cta {
    467          font-size: inherit;
    468        }
    469 
    470        .primary,
    471        .secondary {
    472          padding: 4px 16px;
    473          margin: 0;
    474          font-size: 0.813em;
    475          font-weight: var(--font-weight-semibold);
    476          line-height: 16px;
    477          min-height: var(--button-min-height);
    478          text-decoration: none;
    479          cursor: default;
    480        }
    481 
    482        .secondary {
    483          background-color: var(--fc-button-background);
    484        }
    485 
    486        .primary {
    487          background-color: var(--fc-primary-button-background);
    488        }
    489 
    490        .split-button-container {
    491          align-items: stretch;
    492 
    493          &:not([hidden]) {
    494            display: flex;
    495          }
    496 
    497          .primary,
    498          .secondary,
    499          .additional-cta {
    500            &:not(.submenu-button) {
    501              border-start-end-radius: 0;
    502              border-end-end-radius: 0;
    503              margin-inline-end: 0;
    504            }
    505 
    506            &:focus-visible {
    507              z-index: 2;
    508            }
    509          }
    510 
    511          .submenu-button {
    512            border-start-start-radius: 0;
    513            border-end-start-radius: 0;
    514            margin-inline-start: 1px;
    515            padding: 8px;
    516            min-height: var(--button-min-height);
    517            min-width: var(--button-min-height);
    518            box-sizing: border-box;
    519            background-image: url('chrome://global/skin/icons/arrow-down.svg');
    520            background-repeat: no-repeat;
    521            background-size: 16px;
    522            background-position: center;
    523            -moz-context-properties: fill;
    524            fill: currentColor;
    525          }
    526        }
    527      }
    528 
    529      .action-buttons .primary,
    530      .action-buttons .secondary,
    531      .dismiss-button {
    532        border-radius: 4px;
    533 
    534        &:focus-visible {
    535          box-shadow: none;
    536          outline: 2px solid var(--fc-accent-color);
    537          outline-offset: 2px;
    538        }
    539 
    540        &:disabled {
    541          opacity: 0.4;
    542          cursor: auto;
    543        }
    544      }
    545 
    546      .action-buttons .secondary,
    547      .dismiss-button {
    548        border: 1px solid var(--fc-button-border);
    549        color: var(--fc-button-color);
    550 
    551        &:hover:not(:disabled),
    552        &[open] {
    553          background-color: var(--fc-button-background-hover);
    554          color: var(--fc-button-color-hover);
    555          border: 1px solid var(--fc-button-border-hover);
    556 
    557          &:active {
    558            background-color: var(--fc-button-background-active);
    559            color: var(--fc-button-color-active);
    560            border: 1px solid var(--fc-button-border-active);
    561          }
    562        }
    563      }
    564 
    565      .action-buttons .primary {
    566        border: 1px solid var(--fc-primary-button-border);
    567        color: var(--fc-primary-button-color);
    568 
    569        &:hover:not(:disabled),
    570        &[open] {
    571          background-color: var(--fc-primary-button-background-hover);
    572          color: var(--fc-primary-button-color-hover);
    573          border: 1px solid var(--fc-primary-button-border-hover);
    574 
    575          &:active {
    576            background-color: var(--fc-primary-button-background-active);
    577            color: var(--fc-primary-button-color-active);
    578            border: 1px solid var(--fc-primary-button-border-active);
    579          }
    580        }
    581      }
    582 
    583      .action-checklist {
    584        display: flex;
    585        flex-direction: column;
    586 
    587        .action-checklist-subtitle {
    588          text-align: start;
    589          margin-block-end: 8px;
    590        }
    591 
    592        .action-checklist-divider {
    593          margin-block: 0;
    594          width: 100%;
    595          color: var(--fc-button-background);
    596        }
    597 
    598        .action-checklist-progress-bar {
    599          width: 100%;
    600          height: 6px;
    601          padding-block: 0;
    602          background-color: color-mix(in srgb, var(--fc-color) 25%, transparent);
    603          opacity: 1;
    604          transition: none;
    605          border-radius: 8px;
    606          display: flex;
    607          justify-content: flex-start;
    608          margin-block-end: 16px;
    609 
    610          &:dir(rtl) {
    611            justify-content: flex-end;
    612          }
    613 
    614          .indicator {
    615            width: var(--action-checklist-progress-bar-progress);
    616            height: 100%;
    617            background-color: var(--fc-accent-color);
    618            border: 0;
    619            border-radius: 8px;
    620            opacity: 1;
    621            transition: var(--progress-bar-transition);
    622          }
    623        }
    624 
    625        .action-checklist-items {
    626          display: flex;
    627          flex-direction: column;
    628 
    629          button {
    630            &:first-child {
    631              margin-block-start: 0;
    632            }
    633 
    634            &:last-child {
    635              margin-block-end: 0;
    636            }
    637 
    638            // TODO: This is (very) likely to change
    639            &:not(:disabled):hover {
    640              background-color: var(--fc-button-background-hover);
    641            }
    642 
    643            &:disabled {
    644              color: var(--fc-color);
    645            }
    646 
    647            .action-checklist-label-container {
    648              display: flex;
    649              align-items: center;
    650 
    651              span {
    652                text-align: start;
    653              }
    654 
    655              .check-icon-container {
    656                margin-block-start: 2px;
    657              }
    658 
    659              .check-empty, .check-filled {
    660                margin-inline-end: 8px;
    661                flex-shrink: 0;
    662              }
    663 
    664              .check-empty {
    665                border-radius: 50%;
    666                width: 0.75em;
    667                height: 0.75em;
    668                border: 2px solid color-mix(in srgb, var(--fc-color) 25%, transparent);
    669              }
    670 
    671              .check-filled {
    672                background-image: url('chrome://global/skin/icons/check-filled.svg');
    673                fill: var(--fc-icon-success-color);
    674              }
    675            }
    676 
    677            .external-link-icon, .check-filled {
    678              border: none;
    679              width: 1em;
    680              height: 1em;
    681              background-repeat: no-repeat;
    682              background-position: center;
    683              background-size: contain;
    684              -moz-context-properties: fill;
    685            }
    686 
    687            .external-link-icon-container {
    688              .external-link-icon {
    689                background-image: url('chrome://global/skin/icons/open-in-new.svg');
    690                fill: var(--fc-color);
    691              }
    692            }
    693 
    694            background: none;
    695            display: flex;
    696            justify-content: space-between;
    697            align-items: center;
    698            margin-inline: 0;
    699            margin-block: 4px;
    700            border: none;
    701            border-radius: 4px;
    702            padding-block: 8px;
    703          }
    704        }
    705      }
    706    }
    707  }
    708 
    709  @at-root panel#{&}:is([side='top'], [side='bottom']):not([hide-arrow='permanent']) {
    710    margin-inline: var(--panel-margin-offset);
    711  }
    712 
    713  @at-root panel#{&}:is([side='left'], [side='right']):not([hide-arrow='permanent']) {
    714    margin-block: var(--panel-margin-offset);
    715  }
    716 
    717  @at-root panel#{&}::part(content) {
    718    position: relative;
    719  }
    720 
    721  // all visible callout arrow boxes. boxes are for rotating 45 degrees, arrows
    722  // are for the actual arrow shape and are children of the boxes.
    723  .arrow-box {
    724    position: absolute;
    725    overflow: visible;
    726    transform: rotate(45deg);
    727    // keep the border crisp under transformation
    728    transform-style: preserve-3d;
    729  }
    730 
    731  &:not([arrow-position]) .arrow-box,
    732  &[hide-arrow] .arrow-box {
    733    display: none;
    734  }
    735 
    736  // both shadow arrow and background arrow
    737  .arrow {
    738    width: var(--arrow-square-size);
    739    height: var(--arrow-square-size);
    740  }
    741 
    742  // the arrow's shadow box
    743  .shadow-arrow-box {
    744    z-index: -1;
    745  }
    746 
    747  // the arrow's shadow
    748  .shadow-arrow {
    749    background: transparent;
    750    outline: 1px solid var(--fc-border);
    751    box-shadow: 0 2px 5px rgba(0, 0, 0, 15%);
    752  }
    753 
    754  // the 'filled' arrow box
    755  .background-arrow-box {
    756    z-index: 1;
    757    // the background arrow technically can overlap the dismiss button. it
    758    // doesn't visibly overlap it because of the clip-path rule below, but it
    759    // can still be clicked. so we need to make sure it doesn't block inputs on
    760    // the button. the visible part of the arrow can still catch clicks because
    761    // we don't add this rule to .shadow-arrow-box.
    762    pointer-events: none;
    763  }
    764 
    765  // the 'filled' arrow
    766  .background-arrow {
    767    background: var(--fc-background);
    768    clip-path: var(--fc-arrow-clip-path);
    769  }
    770 
    771  // top (center) arrow positioning
    772  &[arrow-position='top'] .arrow-box {
    773    top: var(--arrow-offset);
    774    inset-inline-start: var(--arrow-center-inset);
    775    // the callout arrow is actually a diamond (a rotated square), with the
    776    // lower half invisible. the part that appears in front of the callout has
    777    // only a background, so that where it overlaps the callout's border, the
    778    // border is not visible. the part that appears behind the callout has only
    779    // a border/shadow, so that it can't be seen overlapping the callout. but
    780    // because the background is the same color as the callout, that half of the
    781    // diamond would visibly overlap any callout content that happens to be in
    782    // the same place. so we clip it to a triangle, with a 2% extension on the
    783    // bottom to account for any subpixel rounding differences.
    784    --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0);
    785  }
    786 
    787  @at-root panel#{&}[arrow-position='top']::part(content) {
    788    margin-top: var(--panel-arrow-space);
    789  }
    790 
    791  @at-root panel#{&}[arrow-position='top'] {
    792    margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    793  }
    794 
    795  // bottom (center) arrow positioning
    796  &[arrow-position='bottom'] .arrow-box {
    797    bottom: var(--arrow-offset);
    798    inset-inline-start: var(--arrow-center-inset);
    799    --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%);
    800  }
    801 
    802  @at-root panel#{&}[arrow-position='bottom']::part(content) {
    803    margin-bottom: var(--panel-arrow-space);
    804  }
    805 
    806  @at-root panel#{&}[arrow-position='bottom'] {
    807    margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    808  }
    809 
    810  // end (center) arrow positioning
    811  &[arrow-position='inline-end'] .arrow-box {
    812    top: var(--arrow-center-inset);
    813    inset-inline-end: var(--arrow-offset);
    814    --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0);
    815  }
    816 
    817  @at-root panel#{&}[arrow-position='inline-end']::part(content) {
    818    margin-inline-end: var(--panel-arrow-space);
    819  }
    820 
    821  @at-root panel#{&}[arrow-position='inline-end'] {
    822    margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    823  }
    824 
    825  // start (center) arrow positioning
    826  &[arrow-position='inline-start'] .arrow-box {
    827    top: var(--arrow-center-inset);
    828    inset-inline-start: var(--arrow-offset);
    829    --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0);
    830  }
    831 
    832  @at-root panel#{&}[arrow-position='inline-start']::part(content) {
    833    margin-inline-start: var(--panel-arrow-space);
    834  }
    835 
    836  @at-root panel#{&}[arrow-position='inline-start'] {
    837    margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    838  }
    839 
    840  // top-end arrow positioning
    841  &[arrow-position='top-end'] .arrow-box {
    842    top: var(--arrow-offset);
    843    inset-inline-end: var(--arrow-corner-inset);
    844    --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0);
    845  }
    846 
    847  @at-root panel#{&}[arrow-position='top-end']::part(content) {
    848    margin-top: var(--panel-arrow-space);
    849  }
    850 
    851  @at-root panel#{&}[arrow-position='top-end'] {
    852    margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    853  }
    854 
    855  // top-start arrow positioning
    856  &[arrow-position='top-start'] .arrow-box {
    857    top: var(--arrow-offset);
    858    inset-inline-start: var(--arrow-corner-inset);
    859    --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0);
    860  }
    861 
    862  @at-root panel#{&}[arrow-position='top-start']::part(content) {
    863    margin-top: var(--panel-arrow-space);
    864  }
    865 
    866  @at-root panel#{&}[arrow-position='top-start'] {
    867    margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    868  }
    869 
    870  // bottom-end arrow positioning
    871  &[arrow-position='bottom-end'] .arrow-box {
    872    bottom: var(--arrow-offset);
    873    inset-inline-end: var(--arrow-corner-inset);
    874    --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%);
    875  }
    876 
    877  @at-root panel#{&}[arrow-position='bottom-end']::part(content) {
    878    margin-bottom: var(--panel-arrow-space);
    879  }
    880 
    881  @at-root panel#{&}[arrow-position='bottom-end'] {
    882    margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    883  }
    884 
    885  // bottom-start arrow positioning
    886  &[arrow-position='bottom-start'] .arrow-box {
    887    bottom: var(--arrow-offset);
    888    inset-inline-start: var(--arrow-corner-inset);
    889    --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%);
    890  }
    891 
    892  @at-root panel#{&}[arrow-position='bottom-start']::part(content) {
    893    margin-bottom: var(--panel-arrow-space);
    894  }
    895 
    896  @at-root panel#{&}[arrow-position='bottom-start'] {
    897    margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    898  }
    899 
    900  // inline-end-top arrow positioning
    901  &[arrow-position='inline-end-top'] .arrow-box {
    902    top: var(--arrow-corner-inset);
    903    inset-inline-end: var(--arrow-offset);
    904    --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0);
    905  }
    906 
    907  @at-root panel#{&}[arrow-position='inline-end-top']::part(content) {
    908    margin-inline-end: var(--panel-arrow-space);
    909  }
    910 
    911  @at-root panel#{&}[arrow-position='inline-end-top'] {
    912    margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    913  }
    914 
    915  // inline-end-bottom arrow positioning
    916  &[arrow-position='inline-end-bottom'] .arrow-box {
    917    bottom: var(--arrow-corner-inset);
    918    inset-inline-end: var(--arrow-offset);
    919    --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0);
    920  }
    921 
    922  @at-root panel#{&}[arrow-position='inline-end-bottom']::part(content) {
    923    margin-inline-end: var(--panel-arrow-space);
    924  }
    925 
    926  @at-root panel#{&}[arrow-position='inline-end-bottom'] {
    927    margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    928  }
    929 
    930  // inline-start-top arrow positioning
    931  &[arrow-position='inline-start-top'] .arrow-box {
    932    top: var(--arrow-corner-inset);
    933    inset-inline-start: var(--arrow-offset);
    934    --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0);
    935  }
    936 
    937  @at-root panel#{&}[arrow-position='inline-start-top']::part(content) {
    938    margin-inline-start: var(--panel-arrow-space);
    939  }
    940 
    941  @at-root panel#{&}[arrow-position='inline-start-top'] {
    942    margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    943  }
    944 
    945  // inline-start-bottom arrow positioning
    946  &[arrow-position='inline-start-bottom'] .arrow-box {
    947    bottom: var(--arrow-corner-inset);
    948    inset-inline-start: var(--arrow-offset);
    949    --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0);
    950  }
    951 
    952  @at-root panel#{&}[arrow-position='inline-start-bottom']::part(content) {
    953    margin-inline-start: var(--panel-arrow-space);
    954  }
    955 
    956  @at-root panel#{&}[arrow-position='inline-start-bottom'] {
    957    margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude)));
    958  }
    959 }